Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add power button on dashboard to switch printer on #1254

Merged
Merged
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
26 changes: 26 additions & 0 deletions src/components/mixins/base.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Vue from 'vue'
import Component from 'vue-class-component'
import { DateTimeFormatOptions } from 'vue-i18n'
import { ServerPowerStateDevice } from '@/store/server/power/types'

@Component
export default class BaseMixin extends Vue {
Expand Down Expand Up @@ -44,6 +45,31 @@ export default class BaseMixin extends Vue {
return this.klipperReadyForGui && ['printing', 'paused'].includes(this.printer_state)
}

get printerPowerDevice(): string {
let deviceName = this.$store.state.gui.uiSettings.powerDeviceName ?? null
if (deviceName === null) deviceName = 'printer'

return deviceName
}

get isPrinterPowerOff() {
const devices = this.$store.getters['server/power/getDevices'] ?? []
if (devices.length === 0) return false

const deviceIndex = devices.findIndex(
(device: ServerPowerStateDevice) => device.device === this.printerPowerDevice
)
// stop if device is not found
if (deviceIndex === -1) return false

const device = devices[deviceIndex]
// Printer is on, if device status is "on" or "error"
if (device.status !== 'off') return false

// if klippy is not connected (service shutdown) and device.status === off
return !this.klippyIsConnected
}

get loadings(): string[] {
return this.$store.state.socket.loadings ?? []
}
Expand Down
43 changes: 37 additions & 6 deletions src/components/panels/KlippyStatePanel.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div v-if="klipperState !== 'ready' && socketIsConnected">
<v-container v-if="klippyIsConnected" class="pa-0 pb-6">
<v-alert :color="messageType.color" dense text border="left" class="mb-0">
<template v-if="klippyIsConnected">
<v-alert :color="messageType.color" dense text border="left" class="mb-0 mb-6">
<!-- KLIPPER MESSAGE TITLE -->
<p class="font-weight-medium d-flex align-center">
<v-icon :color="messageType.color" class="pr-2">{{ messageType.icon }}</v-icon>
Expand Down Expand Up @@ -68,10 +68,28 @@
<v-progress-circular indeterminate :color="messageType.color"></v-progress-circular>
</v-card-text>
</v-alert>
</v-container>
</template>
<!-- Power OFF panel -->
<template v-else-if="isPrinterPowerOff">
<v-alert dense text border="left" class="mb-6">
<p class="font-weight-medium d-flex align-center">
<v-icon class="pr-2">{{ messageType.icon }}</v-icon>
{{ $t('Panels.KlippyStatePanel.PrinterSwitchedOff') }}
</p>
<p>{{ $t('Panels.KlippyStatePanel.PrinterSwitchedOffDescription') }}</p>
<v-row>
<v-col class="text-center">
<v-btn small outlined text :class="`${messageType.color}--text my-1`" @click="powerOn">
<v-icon class="mr-sm-2">{{ mdiPower }}</v-icon>
{{ $t('Panels.KlippyStatePanel.PowerOn') }}
</v-btn>
</v-col>
</v-row>
</v-alert>
</template>
<!-- DISCONNECTED INFOGRAPHIC -->
<v-container v-if="klipperState === 'disconnected'" class="pa-0">
<v-alert dense text border="left">
<template v-else-if="klipperState === 'disconnected'">
<v-alert dense text border="left" class="mb-6">
<p class="font-weight-medium d-flex align-center">
<v-icon class="pr-2">{{ messageType.icon }}</v-icon>
{{ $t('Panels.KlippyStatePanel.ServiceReports', { service: 'Moonraker' }) }}:
Expand All @@ -81,7 +99,7 @@
<p class="mt-2 mb-0 text-center">{{ $t('Panels.KlippyStatePanel.MoonrakerCannotConnect') }}</p>
<p class="mb-0 text-center">{{ $t('Panels.KlippyStatePanel.KlipperCheck') }}</p>
</v-alert>
</v-container>
</template>
</div>
</template>

Expand All @@ -99,6 +117,7 @@ import {
mdiRocketLaunch,
mdiConnection,
mdiPrinter3d,
mdiPower,
} from '@mdi/js'

@Component({
Expand All @@ -108,6 +127,7 @@ export default class KlippyStatePanel extends Mixins(BaseMixin) {
mdiPrinter3d = mdiPrinter3d
mdiRestart = mdiRestart
mdiDownload = mdiDownload
mdiPower = mdiPower

get klippy_message() {
return this.$store.state.server.klippy_message ?? null
Expand Down Expand Up @@ -144,5 +164,16 @@ export default class KlippyStatePanel extends Mixins(BaseMixin) {

window.open(href)
}

powerOn() {
this.$socket.emit(
'machine.device_power.post_device',
{
device: this.printerPowerDevice,
action: 'on',
},
{ action: 'server/power/responseToggle' }
)
}
}
</script>
51 changes: 49 additions & 2 deletions src/components/settings/SettingsUiSettingsTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
color="primary"
href="https://docs.mainsail.xyz/quicktips/thumbnails"
target="_blank">
{{ $t('Settings.UiSettingsTab.Guide') }}
{{ $t('Settings.UiSettingsTab.Guide').toString() }}
</v-btn>
</settings-row>
<v-divider class="my-2"></v-divider>
Expand Down Expand Up @@ -130,7 +130,6 @@
class="mt-0"
hide-details
outlined
attach
dense></v-select>
</settings-row>
<v-divider class="my-2"></v-divider>
Expand All @@ -140,6 +139,19 @@
:dynamic-slot-width="true">
<v-switch v-model="boolHideUploadAndPrintButton" hide-details class="mt-0"></v-switch>
</settings-row>
<v-divider class="my-2"></v-divider>
<settings-row
:title="$t('Settings.UiSettingsTab.PowerDeviceName').toString()"
:sub-title="$t('Settings.UiSettingsTab.PowerDeviceNameDescription').toString()"
:dynamic-slot-width="true">
<v-select
v-model="powerDeviceName"
:items="powerDeviceOptions"
class="mt-0"
hide-details
outlined
dense />
</settings-row>
</v-card-text>
</v-card>
</div>
Expand All @@ -153,6 +165,7 @@ import SettingsRow from '@/components/settings/SettingsRow.vue'
import { defaultLogoColor, defaultPrimaryColor } from '@/store/variables'
import { Debounce } from 'vue-debounce-decorator'
import { mdiRestart, mdiTimerOutline } from '@mdi/js'
import { ServerPowerStateDevice } from '@/store/server/power/types'

@Component({
components: { SettingsRow },
Expand Down Expand Up @@ -271,6 +284,40 @@ export default class SettingsUiSettingsTab extends Mixins(BaseMixin) {
this.$store.dispatch('gui/saveSetting', { name: 'uiSettings.boolHideUploadAndPrintButton', value: newVal })
}

get powerDevices() {
return this.$store.getters['server/power/getDevices'] ?? []
}

get autoPowerDevice() {
const autoIndex = this.powerDevices.findIndex((device: ServerPowerStateDevice) => device.device === 'printer')
if (autoIndex === -1) return '--'

return this.powerDevices[autoIndex].device
}

get powerDeviceName() {
return this.$store.state.gui.uiSettings.powerDeviceName ?? null
}

set powerDeviceName(newVal) {
this.$store.dispatch('gui/saveSetting', { name: 'uiSettings.powerDeviceName', value: newVal })
}

get powerDeviceOptions() {
const items: { text: string; value: string | null }[] = [
{ text: `Auto (${this.autoPowerDevice})`, value: null },
]

this.powerDevices.forEach((device: ServerPowerStateDevice) => {
items.push({
text: `${device.device} (${device.type})`,
value: device.device.toString(),
})
})

return items
}

clearColorObject(color: any): string {
if (typeof color === 'object' && 'hex' in color) color = color.hex
if (color.length > 7) color = color.substr(0, 7)
Expand Down
3 changes: 3 additions & 0 deletions src/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,9 @@
"FirmwareRestart": "Firmware Neustart",
"KlipperCheck": "Bitte überprüfen Sie, ob der Klipper-Dienst läuft und ein UDS (Unix Domain Socket) konfiguriert ist.",
"MoonrakerCannotConnect": "Moonraker kann keine Verbindung zu Klipper herstellen!",
"PowerOn": "Drucker einschalten",
"PrinterSwitchedOff": "Drucker ist ausgeschaltet",
"PrinterSwitchedOffDescription": "Der Drucker ist ausgeschaltet und es kann keine Verbindung zu Klipper hergestellt werden. Um den Drucker einzuschalten, auf die Schaltfläche unten klicken:",
"Restart": "Neustart",
"ServiceReports": "{service} meldet"
},
Expand Down
5 changes: 5 additions & 0 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,9 @@
"FirmwareRestart": "Firmware Restart",
"KlipperCheck": "Please check if the Klipper service is running.",
"MoonrakerCannotConnect": "Moonraker can't connect to Klipper!",
"PowerOn": "Power on",
"PrinterSwitchedOff": "Printer is powered off",
"PrinterSwitchedOffDescription": "The printer is currently powered off and Klipper cannot connect. To power on the printer, click the button below:",
"Restart": "Restart",
"ServiceReports": "{service} reports"
},
Expand Down Expand Up @@ -1006,6 +1009,8 @@
"NavigationStyleDescription": "Change navigation appearance",
"NavigationStyleIconsAndText": "Icons + Text",
"NavigationStyleIconsOnly": "Icons only",
"PowerDeviceName": "Printer power device",
"PowerDeviceNameDescription": "Select which Moonraker power device should be used to power on the printer.",
"Primary": "Primary",
"ShowWebcamInNavigation": "Show Webcam in navigation",
"UiSettings": "UI-Settings"
Expand Down
1 change: 1 addition & 0 deletions src/store/gui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ export const getDefaultState = (): GuiState => {
boolHideUploadAndPrintButton: false,
boolWebcamNavi: false,
navigationStyle: 'iconsAndText',
powerDeviceName: null,
},
view: {
blockFileUpload: false,
Expand Down
1 change: 1 addition & 0 deletions src/store/gui/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export interface GuiState {
boolHideUploadAndPrintButton: boolean
boolWebcamNavi: boolean
navigationStyle: 'iconsAndText' | 'iconsOnly'
powerDeviceName: string | null
}
view: {
blockFileUpload: boolean
Expand Down