From 0bd113b944d041192146692de50e33fe4d6c0fd8 Mon Sep 17 00:00:00 2001
From: Cytown <cytown@gmail.com>
Date: Thu, 24 Jun 2021 00:40:32 +0800
Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Power-off=20confirm=20/=20beep=20op?=
 =?UTF-8?q?tions=20(#22191)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 Marlin/Configuration.h               |  2 ++
 Marlin/src/gcode/control/M80_M81.cpp |  4 ++++
 Marlin/src/lcd/marlinui.cpp          |  7 +++++++
 Marlin/src/lcd/marlinui.h            |  4 ++++
 Marlin/src/lcd/menu/menu_main.cpp    | 10 +++++++++-
 buildroot/tests/rambo                |  3 ++-
 6 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index 717cdd9236b..5b7f439fe51 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -366,6 +366,8 @@
 //#define PSU_NAME "Power Supply"
 
 #if ENABLED(PSU_CONTROL)
+  //#define PS_OFF_CONFIRM          // Confirm dialog when power off
+  //#define PS_OFF_SOUND            // Beep 1s when power off
   #define PSU_ACTIVE_STATE LOW      // Set 'LOW' for ATX, 'HIGH' for X-Box
 
   //#define PSU_DEFAULT_OFF         // Keep power off until enabled directly with M80
diff --git a/Marlin/src/gcode/control/M80_M81.cpp b/Marlin/src/gcode/control/M80_M81.cpp
index 1b5ea2f7eff..00a0a310260 100644
--- a/Marlin/src/gcode/control/M80_M81.cpp
+++ b/Marlin/src/gcode/control/M80_M81.cpp
@@ -101,6 +101,10 @@ void GcodeSuite::M81() {
     #endif
   #endif
 
+  #if ENABLED(PS_OFF_SOUND)
+    BUZZ(1000, 659);
+  #endif
+
   safe_delay(1000); // Wait 1 second before switching off
 
   #if HAS_SUICIDE
diff --git a/Marlin/src/lcd/marlinui.cpp b/Marlin/src/lcd/marlinui.cpp
index d2e26afedfd..9de8941ad98 100644
--- a/Marlin/src/lcd/marlinui.cpp
+++ b/Marlin/src/lcd/marlinui.cpp
@@ -1494,6 +1494,13 @@ void MarlinUI::update() {
     TERN_(HAS_LCD_MENU, return_to_status());
   }
 
+  #if BOTH(PSU_CONTROL, PS_OFF_CONFIRM)
+    void MarlinUI::poweroff() {
+      queue.inject_P(PSTR("M81"));
+      goto_previous_screen();
+    }
+  #endif
+
   void MarlinUI::flow_fault() {
     LCD_ALERTMESSAGEPGM(MSG_FLOWMETER_FAULT);
     TERN_(HAS_BUZZER, buzz(1000, 440));
diff --git a/Marlin/src/lcd/marlinui.h b/Marlin/src/lcd/marlinui.h
index 14514e2a656..fa2b09b8734 100644
--- a/Marlin/src/lcd/marlinui.h
+++ b/Marlin/src/lcd/marlinui.h
@@ -334,6 +334,10 @@ public:
     static void resume_print();
     static void flow_fault();
 
+    #if BOTH(PSU_CONTROL, PS_OFF_CONFIRM)
+      static void poweroff();
+    #endif
+
     #if HAS_WIRED_LCD
 
       static millis_t next_button_update_ms;
diff --git a/Marlin/src/lcd/menu/menu_main.cpp b/Marlin/src/lcd/menu/menu_main.cpp
index 921c2435b58..1e79edb8641 100644
--- a/Marlin/src/lcd/menu/menu_main.cpp
+++ b/Marlin/src/lcd/menu/menu_main.cpp
@@ -387,7 +387,15 @@ void menu_main() {
   //
   #if ENABLED(PSU_CONTROL)
     if (powersupply_on)
-      GCODES_ITEM(MSG_SWITCH_PS_OFF, PSTR("M81"));
+      #if ENABLED(PS_OFF_CONFIRM)
+        CONFIRM_ITEM(MSG_SWITCH_PS_OFF,
+          MSG_YES, MSG_NO,
+          ui.poweroff, ui.goto_previous_screen,
+          GET_TEXT(MSG_SWITCH_PS_OFF), (const char *)nullptr, PSTR("?")
+        );
+      #else
+        GCODES_ITEM(MSG_SWITCH_PS_OFF, PSTR("M81"));
+      #endif
     else
       GCODES_ITEM(MSG_SWITCH_PS_ON, PSTR("M80"));
   #endif
diff --git a/buildroot/tests/rambo b/buildroot/tests/rambo
index df2717c715a..9c56a689b03 100755
--- a/buildroot/tests/rambo
+++ b/buildroot/tests/rambo
@@ -32,7 +32,8 @@ opt_enable USE_ZMAX_PLUG REPRAP_DISCOUNT_SMART_CONTROLLER LCD_PROGRESS_BAR LCD_P
            SKEW_CORRECTION SKEW_CORRECTION_FOR_Z SKEW_CORRECTION_GCODE \
            BACKLASH_COMPENSATION BACKLASH_GCODE BAUD_RATE_GCODE BEZIER_CURVE_SUPPORT \
            FWRETRACT ARC_P_CIRCLES CNC_WORKSPACE_PLANES CNC_COORDINATE_SYSTEMS \
-           PSU_CONTROL AUTO_POWER_CONTROL POWER_LOSS_RECOVERY POWER_LOSS_PIN POWER_LOSS_STATE POWER_LOSS_RECOVER_ZHOME POWER_LOSS_ZHOME_POS \
+           PSU_CONTROL PS_OFF_CONFIRM PS_OFF_SOUND AUTO_POWER_CONTROL \
+           POWER_LOSS_RECOVERY POWER_LOSS_PIN POWER_LOSS_STATE POWER_LOSS_RECOVER_ZHOME POWER_LOSS_ZHOME_POS \
            SLOW_PWM_HEATERS THERMAL_PROTECTION_CHAMBER LIN_ADVANCE EXTRA_LIN_ADVANCE_K \
            HOST_ACTION_COMMANDS HOST_PROMPT_SUPPORT PINS_DEBUGGING MAX7219_DEBUG M114_DETAIL
 opt_add DEBUG_POWER_LOSS_RECOVERY