Skip to content

Commit

Permalink
feat: added new time estimations + config
Browse files Browse the repository at this point in the history
  • Loading branch information
cadriel committed Sep 30, 2020
1 parent 928695b commit 7b05b82
Show file tree
Hide file tree
Showing 13 changed files with 151 additions and 32 deletions.
2 changes: 1 addition & 1 deletion src/components/inputs/InputSlider.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div>
<div class="d-flex justify-start">
<div class="grey--text text--darken-1 align-self-end">{{ label }}</div>
<div class="grey--text text--lighten-1 text-h5 ml-auto">{{ newValue }}%</div>
<div class="grey--text text--lighten-1 text-h5 ml-auto">{{ newValue.toFixed() }}%</div>
</div>
<v-slider
@change="emitChange(newValue)"
Expand Down
50 changes: 43 additions & 7 deletions src/components/widgets/PrintStatusWidget.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,37 @@
:value="timeEstimates.progress"
color="primary"
>
<span class="percentComplete grey--text text-h5 font-weight-normal">{{ timeEstimates.progress.toFixed() }}%</span>
<span class="percentComplete grey--text text-h5 font-weight-normal">{{ timeEstimates.progress }}%</span>
</v-progress-circular>
</v-col>
<v-col class="d-flex flex-column" style="overflow: hidden;" align="start">
<div class="mb-1 grey--text">
<div class="mb-1 grey--text" v-if="printTimeEstimationsType !== 'totals'">
<v-tooltip left>
<template v-slot:activator="{ on, attrs }">
<v-icon v-bind="attrs" v-on="on" color="grey darken-2">mdi-timer-sand</v-icon>
</template>
estimated time left
<span>estimated time left</span>
</v-tooltip>
{{ timeEstimates.timeLeft }}
</div>
<div class="mb-1 grey--text">
<v-tooltip left>
<template v-slot:activator="{ on, attrs }">
<v-icon v-bind="attrs" v-on="on" color="grey darken-2">mdi-clock-outline</v-icon>
<v-icon v-bind="attrs" v-on="on" color="grey darken-2" class="mr-1">mdi-clock-outline</v-icon>
</template>
{{ (printTimeEstimationsType !== 'totals') ? 'duration &amp; total' : 'duration' }}
</v-tooltip>
<span>{{ timeEstimates.duration }}</span>
<span class="grey--text text--darken-2" v-if="printTimeEstimationsType !== 'totals'"> / {{ timeEstimates.totalDuration }}</span>
</div>
<div class="mb-1 grey--text" v-if="filamentEstimates !== ''">
<v-tooltip left>
<template v-slot:activator="{ on, attrs }">
<v-icon v-bind="attrs" v-on="on" color="grey darken-2" class="mr-1">mdi-format-line-spacing</v-icon>
</template>
duration &amp; total
used filament
</v-tooltip>
{{ timeEstimates.duration }} <span class="grey--text text--darken-2">/ {{ timeEstimates.totalDuration }}</span>
<span class="grey--text text--darken-2">{{ filamentEstimates }}</span>
</div>
<div class="d-flex grey--text text--darken-2">
<v-icon color="grey darken-2">mdi-file-document-outline</v-icon>
Expand Down Expand Up @@ -124,10 +134,36 @@ export default class PrintStatusWidget extends Mixins(UtilsMixin) {
return this.$store.state.socket.printer.print_stats.filename
}
get printTimeEstimationsType () {
return this.$store.state.config.fileConfig.general.printTimeEstimationsType
}
get timeEstimates () {
return this.$store.getters['socket/getTimeEstimates']('slicer')
return this.$store.getters['socket/getTimeEstimates'](this.printTimeEstimationsType)
}
get filamentEstimates () {
const filamentUsed = this.$store.state.socket.printer.print_stats.filament_used || 0
const filamentTotal = this.$store.state.socket.printer.current_file.filament_total || 0
if (filamentUsed > 0) {
if (filamentTotal > 0) {
return `${this.$filters.getReadableLengthString(filamentUsed)} / ${this.$filters.getReadableLengthString(filamentTotal)}`
} else {
return this.$filters.getReadableLengthString(filamentUsed)
}
} else {
return ''
}
}
// get usedFilament () {
// return this.$store.state.socket.printer.print_stats.filament_used
// }
// get estimatedTotalFilament () {
// return this.$store.state.socket.printer.current_file.filament_total
// }
cancelPrint () {
SocketActions.printerPrintCancel()
}
Expand Down
42 changes: 40 additions & 2 deletions src/components/widgets/settings/GeneralSettingsWidget.vue
Original file line number Diff line number Diff line change
@@ -1,24 +1,54 @@
<template>
<v-card>
<v-card-title>General Settings</v-card-title>
<v-card-subtitle>General application wide settings.</v-card-subtitle>
<v-card-subtitle>General settings.</v-card-subtitle>
<v-divider></v-divider>
<v-card-text>
<p>
Print times can be estimated based on the slicer data, filament used or klipper. <br />
Alternatively you can choose to just present the current print time and progress. <br />
Slicer estimations tend to hit under actual print time, but the total does not fluctuate. <br />
Klipper and Filament estimations get more accurate over time.
</p>
<v-radio-group
v-model="printTimeEstimationsType"
:mandatory="true">
<v-radio label="Current print duration only" value="totals"></v-radio>
<v-radio label="Slicer data for total print time" value="slicer"></v-radio>
<v-radio label="Klipper estimations (Accuracy over time)" value="file"></v-radio>
<v-radio label="Filament used for total print time" value="filament"></v-radio>
</v-radio-group>
</v-card-text>
<v-divider></v-divider>
<v-card-text>
<v-text-field
filled
label="Camera URL"
v-model="cameraUrl"
></v-text-field>
</v-card-text>
<v-divider></v-divider>
<v-card-text>
<p>Preselects the default extrude length and speed on the dasboard.</p>
<v-text-field
filled
label="Default Extrude Length"
suffix="mm"
v-model="defaultExtrudeLength"
></v-text-field>
<v-text-field
filled
label="Default Extrude Speed"
suffix="mm/s"
v-model="defaultExtrudeSpeed"
></v-text-field>
</v-card-text>
<v-divider></v-divider>
<v-card-text>
<p>Preselects the toolhead move speed on the dashboard.</p>
<v-select
label="Default Toolhead Move Length"
filled
label="Default toolhead move length"
suffix="mm"
:items="['0.1', '1.0', '10', '100']"
v-model="defaultToolheadMoveLength">
Expand Down Expand Up @@ -66,5 +96,13 @@ export default class GeneralSettingsWidget extends Mixins(UtilsMixin) {
set defaultToolheadMoveLength (value: number) {
this.$store.dispatch('config/saveGeneric', { key: 'fileConfig.general.defaultToolheadMoveLength', value })
}
get printTimeEstimationsType () {
return this.$store.state.config.fileConfig.general.printTimeEstimationsType
}
set printTimeEstimationsType (value: string) {
this.$store.dispatch('config/saveGeneric', { key: 'fileConfig.general.printTimeEstimationsType', value })
}
}
</script>
1 change: 1 addition & 0 deletions src/components/widgets/settings/MacroSettingsWidget.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<v-card>
<v-card-title>Dashboard Macros</v-card-title>
<v-card-subtitle>Configure which macros appear on the dashboard.</v-card-subtitle>
<v-divider></v-divider>
<v-card-text>
<v-row>
<v-col cols="12" md="6" class="py-0" v-for="(macro) in macros" :key="macro.name">
Expand Down
9 changes: 9 additions & 0 deletions src/plugins/filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ const Filters = {
return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i]
},

/**
* Formats a number representing mm to m if > 1000
*/
getReadableLengthString (lengthInMm: number) {
if (lengthInMm > 1000) return (lengthInMm / 1000).toFixed(2) + 'm'
return (lengthInMm / 1000).toFixed(2) + 'mm'
},

/**
* The filesystem sorter. This is copied from vuetify, and modified to ensure our directories
* are always sorted to the top.
Expand Down Expand Up @@ -134,6 +142,7 @@ declare module 'vue/types/vue' {
capitalize(string: string): string;
formatFileDateTime(datetime: string): string;
getReadableFileSizeString(fileSizeInBytes: number): string;
getReadableLengthString(lengthInMm: number): string;
/* eslint-disable @typescript-eslint/no-explicit-any */
fileSystemSort(items: Array<any>, sortBy: string[], sortDesc: boolean[], locale: string): Array<any>;
/* eslint-enable @typescript-eslint/no-explicit-any */
Expand Down
9 changes: 6 additions & 3 deletions src/store/config/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,16 @@ export const actions: ActionTree<ConfigState, RootState> = {
* under state.config.fileConfig
*/
async saveGeneric ({ commit }, config: GenericSave) {
commit('setUnsavedChanges', true)
commit('onSaveGeneric', config)
},

/**
*
*/
async updateHiddenMacros (_, payload) {
console.log('updateHiddenMacros', payload)
async updateHiddenMacros ({ commit }, payload) {
commit('setUnsavedChanges', true)
commit('updateHiddenMacros', payload)
},

/**
Expand All @@ -55,7 +57,7 @@ export const actions: ActionTree<ConfigState, RootState> = {
/**
* Saves fileConfig to file.
*/
async saveFileConfig ({ state, rootState }) {
async saveFileConfig ({ commit, state, rootState }) {
if (state.fileConfig && Object.keys(state.fileConfig).length > 0) {
const formData = new FormData()
const filename = Globals.SETTINGS_FILENAME
Expand All @@ -74,5 +76,6 @@ export const actions: ActionTree<ConfigState, RootState> = {
}
)
}
commit('setUnsavedChanges', false)
}
}
1 change: 1 addition & 0 deletions src/store/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const state: ConfigState = {
},
fileConfig: {
general: {
printTimeEstimationsType: 'filament',
defaultExtrudeLength: 10,
defaultExtrudeSpeed: 5,
defaultToolheadMoveLength: '1.0'
Expand Down
4 changes: 2 additions & 2 deletions src/store/config/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ export const mutations: MutationTree<ConfigState> = {
/**
* Sets unsaved changes for file config.
*/
setUnsavedChanges (state) {
state.unsavedChanges = true
setUnsavedChanges (state, payload: boolean) {
state.unsavedChanges = payload
},

/**
Expand Down
1 change: 1 addition & 0 deletions src/store/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface GeneralConfig {
defaultExtrudeLength: number;
defaultExtrudeSpeed: number;
defaultToolheadMoveLength: string;
printTimeEstimationsType: 'file' | 'slicer' | 'filament' | 'totals';
}

export interface CameraConfig {
Expand Down
45 changes: 35 additions & 10 deletions src/store/socket/getters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,42 +25,67 @@ export const getters: GetterTree<SocketState, RootState> = {
// printing, busy, paused, ready, idle, standby
if (state1 && state2) {
if (
state1.toLowerCase() === 'printing' &&
state2.toLowerCase() !== 'printing'
state2.toLowerCase() === 'paused'
) {
return 'busy'
return state2
}
if (
state2.toLowerCase() === 'paused'
state1.toLowerCase() === 'printing' &&
state2.toLowerCase() !== 'printing'
) {
return state2
// The printers idle_timeout changes to printing when it's busy applying
// some change - but not necessarily printing anything. This state hopefully
// helps aleviate that confusion.
return 'Busy'
}
return state1
} else {
return 'ready'
return 'Loading'
}
},

/**
* Returns an object representing the time estimates of a current print.
*/
getTimeEstimates: (state) => (type: 'slicer' | 'file' | 'filament'): TimeEstimates => {
getTimeEstimates: (state) => (type: 'slicer' | 'file' | 'filament' | 'totals'): TimeEstimates => {
// const filename = state.printer.print_stats.filename
const progress = state.printer.display_status.progress * 100
const duration = state.printer.print_stats.print_duration
const progress = state.printer.display_status.progress || 0
const duration = state.printer.print_stats.print_duration || 0
const usedFilament = state.printer.print_stats.filament_used || 0
const estimatedFilament = state.printer.current_file.filament_total || 0
let timeLeft = 0
let totalDuration = 0

switch (type) {
case 'slicer': {
totalDuration = (state.printer.current_file.estimated_time > 0) ? state.printer.current_file.estimated_time : duration
timeLeft = totalDuration - duration
break
}
case 'filament': {
totalDuration = duration / (usedFilament / estimatedFilament) - duration
timeLeft = totalDuration - duration
break
}
case 'file': {
totalDuration = duration / (progress) - duration
timeLeft = totalDuration - duration
break
}
case 'totals': { // totals only.
totalDuration = 0
timeLeft = 0
break
}
default: { // totals only.
totalDuration = duration / (progress * 100) - duration
timeLeft = totalDuration - duration
}
}

return {
type,
progress: progress,
progress: (progress * 100).toFixed(),
timeLeft: Vue.$filters.formatCounterTime(timeLeft),
duration: Vue.$filters.formatCounterTime(duration),
totalDuration: Vue.$filters.formatCounterTime(totalDuration)
Expand Down
4 changes: 2 additions & 2 deletions src/store/socket/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ export interface SocketError {
}

export interface TimeEstimates {
type: 'file' | 'slicer' | 'filament';
progress: number;
type: 'file' | 'slicer' | 'filament' | 'totals';
progress: string;
timeLeft: string;
duration: string;
totalDuration: string;
Expand Down
6 changes: 5 additions & 1 deletion src/views/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<v-card-title>
<v-icon large left>mdi-cog</v-icon>
<span class="title font-weight-light text-h5">UI Settings</span>
<v-btn color="primary" class="ml-auto" @click="saveFileConfig()"><v-icon class="mr-2">mdi-content-save-alert-outline</v-icon> Save Changes</v-btn>
<v-btn :color="(hasUnsavedChanges) ? 'error' : 'primary'" class="ml-auto" @click="saveFileConfig()"><v-icon class="mr-2">mdi-content-save-alert-outline</v-icon> Save Changes</v-btn>
</v-card-title>
</v-card>
<v-row>
Expand Down Expand Up @@ -38,6 +38,10 @@ import TemperaturePresetsSettingsWidget from '@/components/widgets/settings/Temp
}
})
export default class Settings extends Mixins(UtilsMixin) {
get hasUnsavedChanges () {
return this.$store.state.config.unsavedChanges
}
saveFileConfig () {
this.$store.dispatch('config/saveFileConfig')
}
Expand Down
9 changes: 5 additions & 4 deletions todo.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
# TODO [fluidd]

## Next Up
- add a throttle to temp updates, print timers, position trackers.
- Add initial documentation
- Add initial commit requirements / help
- add other types of print time estimates
- toasts on error (like move is out of bounds!!)
- Figure out a first release zip + process
- Printer setup page + bed levelling

## Known Bugs:
- during pause / resume - the button states change incorrectly
Expand All @@ -15,6 +14,8 @@
- the metadata load fails because the file is no longer there.

## General Improvements
- add console.log wrapper for dev vs prod
- add a throttle to temp updates, print timers, position trackers.
- Performance / memory heap checks
- bed levelling
- filament sensor status
Expand Down

0 comments on commit 7b05b82

Please sign in to comment.