Skip to content

Commit

Permalink
feat: lockable sliders (#412)
Browse files Browse the repository at this point in the history
* fix: replace tab characters by spaces

Signed-off-by: Dominik Willner <[email protected]>

* fix: replace tab characters by spaces

Signed-off-by: Dominik Willner <[email protected]>

* feature: add lockable sliders

Signed-off-by: Dominik Willner <[email protected]>

* feat: add lockable sliders

feat: add auto-lock sliders

Signed-off-by: Dominik Willner <[email protected]>

* locale: add EN locale for LockSlider and AutoLockSlider features.

Signed-off-by: Dominik Willner <[email protected]>

* chore: rename autoLockSliders to lockSliders

refactor: include startLockTimer method in sendCmd method

Signed-off-by: Dominik Willner <[email protected]>

* refactor: refactor startLockTimer method

Signed-off-by: Dominik Willner <[email protected]>

* refactor: lockSlidersChanged Watcher

Signed-off-by: Dominik Willner <[email protected]>

* refactor: remove helper, use new isTouchDevice BaseMixin method instead

Signed-off-by: Dominik Willner <[email protected]>

* feat: add lockable sliders to miscellaneous sliders

Signed-off-by: Dominik Willner <[email protected]>

* fix: every interaction with the slider resets timeout correctly

Signed-off-by: Dominik Willner <[email protected]>

* fix: fix typo

Signed-off-by: Dominik Willner <[email protected]>

* chore: remove unused import

Signed-off-by: Dominik Willner <[email protected]>

* chore: remove unused import

Signed-off-by: Dominik Willner <[email protected]>

* chore: replace tabs with spaces

Signed-off-by: Dominik Willner <[email protected]>

* chore: replace tabs with spaces / remove trailing newlines

Signed-off-by: Dominik Willner <[email protected]>

* refactor: rename name/value pairs to a more appropriate name

Signed-off-by: Dominik Willner <[email protected]>

* refactor(locale): update EN locale file

Signed-off-by: Dominik Willner <[email protected]>

* fix: get/set correct store name

Signed-off-by: Dominik Willner <[email protected]>

* refactor: use "Delay" instead of "Timeout"

Signed-off-by: Dominik Willner <[email protected]>

* refactor(locale): update EN locale file

Signed-off-by: Dominik Willner <[email protected]>

* refactor(locale): update DE locale file

Signed-off-by: Dominik Willner <[email protected]>

* refactor: rename menuStyle to navigationStyle

Signed-off-by: Dominik Willner <[email protected]>
  • Loading branch information
dw-0 authored Nov 17, 2021
1 parent de67381 commit 6b8f569
Show file tree
Hide file tree
Showing 17 changed files with 3,580 additions and 3,199 deletions.
94 changes: 47 additions & 47 deletions docs/faq/klipper_errors/command_format_mismatch.md
Original file line number Diff line number Diff line change
@@ -1,48 +1,48 @@
---
layout: default
title: Command format mismatch
parent: Klipper Errors
grand_parent: FAQ
nav_order: 10
has_children: false
permalink: /faq/klipper_errors/command_format_mismatch
has_toc: false
description: >-
You have updated Klipper and now you get this cryptic error message? We would like to help...
---

# Klipper Error - Command format mismatch

You have updated Klipper and now you get this cryptic error message?

![Command format mismatch](../../assets/img/faq/errors/mcu_error.png)

This is an error and needs to be fixed to make Mainsail and Klipper work again.
{: .info}

## TL;DR

Klipper on your host and on your MCU have different versions.
Recompile and flash your MCUs and it will work again. Please also pay attention to the "Linux MCU", if you had e.g. an adxl345 in use.

The following links should help you to solve the problem:
[Klipper SD-Card Updates](https://www.klipper3d.org/SDCard_Updates.html){:target="_blank"}
[Klipper Building and flashing the micro-controller](https://www.klipper3d.org/Installation.html#building-and-flashing-the-micro-controller){:target="_blank"}

## More detailed

Klipper consists of two parts:
The software on your host (e.g. Raspberry Pi) and the firmware on your microcontroller (MCU).

Under normal circumstances, Klipper (on your host) can simply be updated from Mainsail without any problems and everything will work as expected.

From time to time it happens that there are changes in Klipper that make it necessary to update all your MCUs. Assuming you have run a Klipper update and Klipper on your host now supports commands that your MCUs does not understand. Then you will get the above error message.

Fortunately, these kind of updates don't happen very often, but now it has happened to you. ;-)

In order to solve the problem, you need to update all your MCUs. We are talking about multiple MCUs here, as people tend to forget that they have multiple microcontrollers in use. One of these candidates is the "Linux MCU" that many people install on their Raspberry Pi to measure resonances with an adxl345.

Detailed information on how to update the firmware can be found in the Klipper Documentation linked above (under TL;DR).

As far as we know, work is in progress to let Klipper update the firmware on its own.
---
layout: default
title: Command format mismatch
parent: Klipper Errors
grand_parent: FAQ
nav_order: 10
has_children: false
permalink: /faq/klipper_errors/command_format_mismatch
has_toc: false
description: >-
You have updated Klipper and now you get this cryptic error message? We would like to help...
---

# Klipper Error - Command format mismatch

You have updated Klipper and now you get this cryptic error message?

![Command format mismatch](../../assets/img/faq/errors/mcu_error.png)

This is an error and needs to be fixed to make Mainsail and Klipper work again.
{: .info}

## TL;DR

Klipper on your host and on your MCU have different versions.
Recompile and flash your MCUs and it will work again. Please also pay attention to the "Linux MCU", if you had e.g. an adxl345 in use.

The following links should help you to solve the problem:
[Klipper SD-Card Updates](https://www.klipper3d.org/SDCard_Updates.html){:target="_blank"}
[Klipper Building and flashing the micro-controller](https://www.klipper3d.org/Installation.html#building-and-flashing-the-micro-controller){:target="_blank"}

## More detailed

Klipper consists of two parts:
The software on your host (e.g. Raspberry Pi) and the firmware on your microcontroller (MCU).

Under normal circumstances, Klipper (on your host) can simply be updated from Mainsail without any problems and everything will work as expected.

From time to time it happens that there are changes in Klipper that make it necessary to update all your MCUs. Assuming you have run a Klipper update and Klipper on your host now supports commands that your MCUs does not understand. Then you will get the above error message.

Fortunately, these kind of updates don't happen very often, but now it has happened to you. ;-)

In order to solve the problem, you need to update all your MCUs. We are talking about multiple MCUs here, as people tend to forget that they have multiple microcontrollers in use. One of these candidates is the "Linux MCU" that many people install on their Raspberry Pi to measure resonances with an adxl345.

Detailed information on how to update the firmware can be found in the Klipper Documentation linked above (under TL;DR).

As far as we know, work is in progress to let Klipper update the firmware on its own.
{: .info}
6 changes: 3 additions & 3 deletions src/components/TheSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
</style>

<template>
<v-navigation-drawer v-model="naviDrawer" :src="sidebarBackground" :mini-variant="(menuStyle === 'iconsOnly')" :key="menuStyle" width="220px" clipped app>
<v-navigation-drawer v-model="naviDrawer" :src="sidebarBackground" :mini-variant="(navigationStyle === 'iconsOnly')" :key="navigationStyle" width="220px" clipped app>
<v-list class="pr-0 pt-0 ml-0">
<v-list-item-group active-class="active-nav-item">
<template v-if="countPrinters">
Expand Down Expand Up @@ -99,8 +99,8 @@ export default class TheSidebarAlt extends Mixins(BaseMixin) {
this.$store.dispatch('setNaviDrawer', newVal)
}
get menuStyle() {
return this.$store.state.gui.dashboard.menuStyle
get navigationStyle() {
return this.$store.state.gui.dashboard.navigationStyle
}
get sidebarBackground(): string {
Expand Down
82 changes: 74 additions & 8 deletions src/components/inputs/MiscellaneousSlider.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,54 @@
<v-row>
<v-col :class="pwm ? 'pb-1' : 'pb-3'">
<v-subheader class="_fan-slider-subheader">
<v-icon small :class="'mr-2 '+(value >= off_below && value > 0 ? 'icon-rotate' : '')" v-if="type !== 'output_pin'">mdi-fan</v-icon>
<v-btn
v-if="canLock && lockSliders && this.isTouchDevice && controllable"
@click="sliderIsLocked = !sliderIsLocked"
plain
small
icon
>
<v-icon small :color="(sliderIsLocked ? 'red' : '')">
{{ sliderIsLocked ? 'mdi-lock-outline' : 'mdi-lock-open-variant-outline' }}
</v-icon>
</v-btn>
<v-icon
small
:class="'mr-2 '+(value >= off_below && value > 0 ? 'icon-rotate' : '')"
v-if="type !== 'output_pin'"
>
mdi-fan
</v-icon>
<span>{{ convertName(name) }}</span>
<v-spacer></v-spacer>
<small v-if="rpm || rpm === 0" :class="'mr-3 ' + (rpm === 0 && value > 0 ? 'red--text' : '')">{{ Math.round(rpm) }} RPM</small>
<span class="font-weight-bold" v-if="!controllable || (controllable && pwm)">{{ Math.round(parseFloat(value)*100) }} %</span>
<v-icon v-if="controllable && !pwm" @click="switchOutputPin">{{ value ? "mdi-toggle-switch" : "mdi-toggle-switch-off-outline" }}</v-icon>
<small v-if="rpm || rpm === 0" :class="'mr-3 ' + (rpm === 0 && value > 0 ? 'red--text' : '')">
{{ Math.round(rpm) }} RPM
</small>
<span class="font-weight-bold" v-if="!controllable || (controllable && pwm)">
{{ Math.round(parseFloat(value)*100) }} %
</span>
<v-icon v-if="controllable && !pwm" @click="switchOutputPin">
{{ value ? "mdi-toggle-switch" : "mdi-toggle-switch-off-outline" }}
</v-icon>
</v-subheader>
<v-card-text class="py-0" v-if="controllable && pwm">
<v-slider
v-model="value"
v-touch="{start: resetLockTimer}"
:disabled="canLock && sliderIsLocked"
:min="0.0"
:max="1.0"
:step="0.01"
:color="value < off_below && value > 0 ? 'red' : undefined"
@change="changeSlicer()"
@change="changeSlider"
hide-details
>
<template v-slot:prepend>
<v-icon @click="decrement">mdi-minus</v-icon>
<v-icon @click="decrement" :disabled="canLock && sliderIsLocked">mdi-minus</v-icon>
</template>

<template v-slot:append>
<v-icon @click="increment">mdi-plus</v-icon>
<v-icon @click="increment" :disabled="canLock && sliderIsLocked">mdi-plus</v-icon>
</template>
</v-slider>
</v-card-text>
Expand All @@ -50,9 +75,12 @@ import {Debounce} from 'vue-debounce-decorator'
@Component
export default class MiscellaneousSlider extends Mixins(BaseMixin) {
convertName = convertName
private timeout: number | undefined
private min = 0
private value = 0
@Prop({ required: true }) readonly sliderName!: string
@Prop({ type: Boolean, default: true, required: true }) readonly canLock!: string
@Prop({ type: Number, required: true }) target!: number
@Prop({ type: Number, default: 1 }) max!: number
@Prop({ type: String, default: '' }) name!: string
Expand All @@ -63,8 +91,44 @@ export default class MiscellaneousSlider extends Mixins(BaseMixin) {
@Prop({ type: Number, default: 1 }) multi!: number
@Prop({ type: Number, default: 0 }) off_below!: number
@Watch('lockSliders', {immediate: true})
lockSlidersChanged(){
if(this.lockSliders && this.isTouchDevice){
this.sliderIsLocked = true
} else {
this.sliderIsLocked = false
}
}
startLockTimer() {
let t = this.lockSlidersDelay
if (!this.isTouchDevice || !this.lockSliders || (t <= 0)) return
this.timeout = setTimeout(() => this.sliderIsLocked = true, t * 1000)
}
resetLockTimer() {
clearTimeout(this.timeout)
}
get lockSliders() {
return this.$store.state.gui.general.lockSlidersOnTouchDevices
}
get lockSlidersDelay() {
return this.$store.state.gui.general.lockSlidersDelay
}
get sliderIsLocked() {
return this.$store.getters['gui/getLockedSliders'](this.sliderName)
}
set sliderIsLocked(newVal) {
if (!this.controllable) return
this.$store.dispatch('gui/saveSliderLockState', { name: this.sliderName, value: newVal })
}
@Debounce(500)
changeSlicer() {
changeSlider() {
this.sendCmd()
}
Expand All @@ -84,6 +148,8 @@ export default class MiscellaneousSlider extends Mixins(BaseMixin) {
this.$store.dispatch('server/addEvent', {message: gcode, type: 'command'})
this.$socket.emit('printer.gcode.script', {script: gcode})
}
this.startLockTimer()
}
switchOutputPin() {
Expand Down
58 changes: 56 additions & 2 deletions src/components/inputs/ToolSlider.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,24 @@
<v-row>
<v-col class="pb-1 pt-3">
<v-subheader class="_tool-slider-subheader">
<v-btn
v-if="canLock && lockSliders && isTouchDevice"
@click="sliderIsLocked = !sliderIsLocked"
plain
small
icon
>
<v-icon small :color="(sliderIsLocked ? 'red' : '')">
{{ sliderIsLocked ? 'mdi-lock-outline' : 'mdi-lock-open-variant-outline' }}
</v-icon>
</v-btn>
<span>{{ label }}</span>
<v-btn
v-if="value !== defaultValue"
class="ml-2"
x-small
icon
:disabled="canLock && sliderIsLocked"
@click="resetSlider"
>
<v-icon>mdi-restart</v-icon>
Expand All @@ -27,18 +39,20 @@
<v-card-text class="py-0">
<v-slider
v-model="value"
v-touch="{start: resetLockTimer}"
:disabled="canLock && sliderIsLocked"
:min="min"
:max="processedMax"
:color="colorBar"
@change="changeSlider"
hide-details>

<template v-slot:prepend>
<v-icon @click="decrement">mdi-minus</v-icon>
<v-icon @click="decrement" :disabled="canLock && sliderIsLocked">mdi-minus</v-icon>
</template>

<template v-slot:append>
<v-icon @click="increment">mdi-plus</v-icon>
<v-icon @click="increment" :disabled="canLock && sliderIsLocked">mdi-plus</v-icon>
</template>
</v-slider>
</v-card-text>
Expand All @@ -55,11 +69,14 @@ import {Debounce} from 'vue-debounce-decorator'
@Component
export default class ToolSlider extends Mixins(BaseMixin) {
private timeout: number | undefined
value = 0
startValue = 0
processedMax = 100
dynamicStep = 50
@Prop({ required: true }) readonly sliderName!: string
@Prop({ type: Boolean, default: true, required: true }) readonly canLock!: string
@Prop({ type: Number, required: true }) readonly target!: number
@Prop({ type: String, required: true }) readonly command!: string
@Prop({ type: String, default: '' }) readonly attributeName!: string
Expand All @@ -83,6 +100,41 @@ export default class ToolSlider extends Mixins(BaseMixin) {
}
}
@Watch('lockSliders', {immediate: true})
lockSlidersChanged(){
if(this.lockSliders && this.isTouchDevice){
this.sliderIsLocked = true
} else {
this.sliderIsLocked = false
}
}
startLockTimer() {
let t = this.lockSlidersDelay
if (!this.isTouchDevice || !this.lockSliders || (t <= 0)) return
this.timeout = setTimeout(() => this.sliderIsLocked = true, t * 1000)
}
resetLockTimer() {
clearTimeout(this.timeout)
}
get lockSliders() {
return this.$store.state.gui.general.lockSlidersOnTouchDevices
}
get lockSlidersDelay() {
return this.$store.state.gui.general.lockSlidersDelay
}
get sliderIsLocked() {
return this.$store.getters['gui/getLockedSliders'](this.sliderName)
}
set sliderIsLocked(newVal) {
this.$store.dispatch('gui/saveSliderLockState', { name: this.sliderName, value: newVal })
}
get colorBar() {
return this.max < this.value ? 'warning' : 'primary'
}
Expand Down Expand Up @@ -126,6 +178,8 @@ export default class ToolSlider extends Mixins(BaseMixin) {
const gcode = this.command + ' ' + this.attributeName + (Math.max(1, this.value) * this.attributeScale).toFixed(0)
this.$store.dispatch('server/addEvent', {message: gcode, type: 'command'})
this.$socket.emit('printer.gcode.script', {script: gcode})
this.startLockTimer()
}
decrement() {
Expand Down
2 changes: 2 additions & 0 deletions src/components/panels/MiscellaneousPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<div v-for="(object, index) of miscellaneous" v-bind:key="index">
<v-divider v-if="index"></v-divider>
<miscellaneous-slider
:slider-name="object.name"
:name="object.name"
:type="object.type"
:target="object.power"
Expand All @@ -22,6 +23,7 @@
:off_below="object.off_below"
:max="object.max_power"
:multi="parseInt(object.scale)"
:can-lock="true"
></miscellaneous-slider>
</div>
<div v-for="(sensor, index) of filamentSensors" v-bind:key="'sensor_'+index">
Expand Down
Loading

0 comments on commit 6b8f569

Please sign in to comment.