Преглед на файлове

Added nozzle indicator for multi nozzle printers

maziggy преди 4 месеца
родител
ревизия
9bfb969169
променени са 6 файла, в които са добавени 32 реда и са изтрити 21 реда
  1. 1 1
      backend/app/main.py
  2. 2 0
      backend/app/services/printer_manager.py
  3. 27 18
      frontend/src/pages/PrintersPage.tsx
  4. 0 0
      static/assets/index-CmQlhkzV.js
  5. 0 0
      static/assets/index-jSEJkRy_.css
  6. 2 2
      static/index.html

+ 1 - 1
backend/app/main.py

@@ -244,7 +244,7 @@ async def on_printer_status_change(printer_id: int, state: PrinterState):
         f"{nozzle_temp}:{bed_temp}:{nozzle_2_temp}:{chamber_temp}:"
         f"{state.stg_cur}:{bed_target}:{nozzle_target}:"
         f"{state.cooling_fan_speed}:{state.big_fan1_speed}:{state.big_fan2_speed}:"
-        f"{state.chamber_light}"
+        f"{state.chamber_light}:{state.active_extruder}"
     )
 
     # MQTT relay - publish status (before dedup check - always publish to MQTT)

+ 2 - 0
backend/app/services/printer_manager.py

@@ -571,6 +571,8 @@ def printer_state_to_dict(state: PrinterState, printer_id: int | None = None, mo
         "heatbreak_fan_speed": state.heatbreak_fan_speed,
         # Chamber light state
         "chamber_light": state.chamber_light,
+        # Active extruder for dual-nozzle printers (0=right, 1=left)
+        "active_extruder": state.active_extruder,
     }
     # Add cover URL if there's an active print and printer_id is provided
     # Include PAUSE/PAUSED states so skip objects modal can show cover

+ 27 - 18
frontend/src/pages/PrintersPage.tsx

@@ -1712,45 +1712,54 @@ function PrinterCard({
               const nozzleHeating = status.temperatures.nozzle_heating || status.temperatures.nozzle_2_heating || false;
               const bedHeating = status.temperatures.bed_heating || false;
               const chamberHeating = status.temperatures.chamber_heating || false;
+              const isDualNozzle = printer.nozzle_count === 2 || status.temperatures.nozzle_2 !== undefined;
+              // active_extruder: 0=right, 1=left
+              const activeNozzle = status.active_extruder === 1 ? 'L' : 'R';
 
               return (
-                <div className="grid grid-cols-3 gap-2">
+                <div className="flex items-center gap-1.5">
                   {/* Nozzle temp - combined for dual nozzle */}
-                  <div className="text-center p-2 bg-bambu-dark rounded-lg">
-                    <HeaterThermometer className="w-4 h-4 mx-auto mb-1" color="text-orange-400" isHeating={nozzleHeating} />
+                  <div className="text-center px-2 py-1.5 bg-bambu-dark rounded-lg flex-1">
+                    <HeaterThermometer className="w-3.5 h-3.5 mx-auto mb-0.5" color="text-orange-400" isHeating={nozzleHeating} />
                     {status.temperatures.nozzle_2 !== undefined ? (
                       <>
-                        <p className="text-[10px] text-bambu-gray">L / R</p>
-                        <p className="text-xs text-white">
+                        <p className="text-[9px] text-bambu-gray">L / R</p>
+                        <p className="text-[11px] text-white">
                           {Math.round(status.temperatures.nozzle || 0)}° / {Math.round(status.temperatures.nozzle_2 || 0)}°
                         </p>
                       </>
                     ) : (
                       <>
-                        <p className="text-[10px] text-bambu-gray">Nozzle</p>
-                        <p className="text-xs text-white">
+                        <p className="text-[9px] text-bambu-gray">Nozzle</p>
+                        <p className="text-[11px] text-white">
                           {Math.round(status.temperatures.nozzle || 0)}°C
                         </p>
                       </>
                     )}
                   </div>
-                  <div className="text-center p-2 bg-bambu-dark rounded-lg">
-                    <HeaterThermometer className="w-4 h-4 mx-auto mb-1" color="text-blue-400" isHeating={bedHeating} />
-                    <p className="text-[10px] text-bambu-gray">Bed</p>
-                    <p className="text-xs text-white">
+                  <div className="text-center px-2 py-1.5 bg-bambu-dark rounded-lg flex-1">
+                    <HeaterThermometer className="w-3.5 h-3.5 mx-auto mb-0.5" color="text-blue-400" isHeating={bedHeating} />
+                    <p className="text-[9px] text-bambu-gray">Bed</p>
+                    <p className="text-[11px] text-white">
                       {Math.round(status.temperatures.bed || 0)}°C
                     </p>
                   </div>
-                  {status.temperatures.chamber !== undefined ? (
-                    <div className="text-center p-2 bg-bambu-dark rounded-lg">
-                      <HeaterThermometer className="w-4 h-4 mx-auto mb-1" color="text-green-400" isHeating={chamberHeating} />
-                      <p className="text-[10px] text-bambu-gray">Chamber</p>
-                      <p className="text-xs text-white">
+                  {status.temperatures.chamber !== undefined && (
+                    <div className="text-center px-2 py-1.5 bg-bambu-dark rounded-lg flex-1">
+                      <HeaterThermometer className="w-3.5 h-3.5 mx-auto mb-0.5" color="text-green-400" isHeating={chamberHeating} />
+                      <p className="text-[9px] text-bambu-gray">Chamber</p>
+                      <p className="text-[11px] text-white">
                         {Math.round(status.temperatures.chamber || 0)}°C
                       </p>
                     </div>
-                  ) : (
-                    <div /> /* Empty placeholder to maintain grid */
+                  )}
+                  {/* Active nozzle indicator for dual-nozzle printers */}
+                  {isDualNozzle && (
+                    <div className="text-center px-2 py-1.5 bg-bambu-dark rounded-lg" title={`Active: ${activeNozzle === 'L' ? 'Left' : 'Right'} nozzle`}>
+                      <p className={`text-[11px] font-bold ${activeNozzle === 'L' ? 'text-amber-400' : 'text-gray-500'}`}>L</p>
+                      <p className="text-[9px] text-bambu-gray">Nozzle</p>
+                      <p className={`text-[11px] font-bold ${activeNozzle === 'R' ? 'text-amber-400' : 'text-gray-500'}`}>R</p>
+                    </div>
                   )}
                 </div>
               );

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
static/assets/index-CmQlhkzV.js


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
static/assets/index-jSEJkRy_.css


+ 2 - 2
static/index.html

@@ -23,8 +23,8 @@
 
     <!-- Splash screens for iOS -->
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
-    <script type="module" crossorigin src="/assets/index-CsUfsUsI.js"></script>
-    <link rel="stylesheet" crossorigin href="/assets/index-DMQ1f41h.css">
+    <script type="module" crossorigin src="/assets/index-CmQlhkzV.js"></script>
+    <link rel="stylesheet" crossorigin href="/assets/index-jSEJkRy_.css">
   </head>
   <body>
     <div id="root"></div>

Някои файлове не бяха показани, защото твърде много файлове са промени