From e040a736b032ecf9f54e353013e6ad5909be0213 Mon Sep 17 00:00:00 2001
From: Manuel Weiser <manuel.weiser@me.com>
Date: Thu, 27 Mar 2025 10:35:10 +0100
Subject: [PATCH] feat: add rfid_bambu.html and update bambu connection
 handling

---
 html/rfid.html       |   9 ---
 html/rfid_bambu.html | 160 +++++++++++++++++++++++++++++++++++++++++++
 src/bambu.cpp        |   6 +-
 src/bambu.h          |   1 +
 src/website.cpp      |   7 +-
 5 files changed, 168 insertions(+), 15 deletions(-)
 create mode 100644 html/rfid_bambu.html

diff --git a/html/rfid.html b/html/rfid.html
index b3b2527..a481c04 100644
--- a/html/rfid.html
+++ b/html/rfid.html
@@ -141,15 +141,6 @@
             </div>
         </div>
 
-        <!-- Rechte Spalte -->
-        <div class="column">
-            <div class="feature-box">
-                <h2>Bambu AMS</h2>
-                <div id="amsDataContainer">
-                    <div class="amsData" id="amsData">Wait for AMS-Data...</div>
-                </div>
-            </div>
-        </div>
     </div>
 </div>
 
diff --git a/html/rfid_bambu.html b/html/rfid_bambu.html
new file mode 100644
index 0000000..b3b2527
--- /dev/null
+++ b/html/rfid_bambu.html
@@ -0,0 +1,160 @@
+<!-- head --><!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>FilaMan - Filament Management Tool</title>
+    <link rel="icon" type="image/png" href="/favicon.ico">
+    <link rel="stylesheet" href="style.css">
+    <script>
+        fetch('/api/version')
+            .then(response => response.json())
+            .then(data => {
+                const versionSpan = document.querySelector('.version');
+                if (versionSpan) {
+                    versionSpan.textContent = 'v' + data.version;
+                }
+            })
+            .catch(error => console.error('Error fetching version:', error));
+    </script>
+</head>
+<body>
+    <div class="navbar">
+        <div style="display: flex; align-items: center; gap: 2rem;">
+            <img src="/logo.png" alt="FilaMan Logo" class="logo">
+            <div class="logo-text">
+                <h1>FilaMan<span class="version"></span></h1>
+                <h4>Filament Management Tool</h4>
+            </div>
+        </div>
+        <nav style="display: flex; gap: 1rem;">
+            <a href="/">Start</a>
+            <a href="/waage">Scale</a>
+            <a href="/spoolman">Spoolman/Bambu</a>
+            <a href="/about">About</a>
+            <a href="/upgrade">Upgrade</a>
+        </nav>
+        <div class="status-container">
+            <div class="status-item">
+                <span class="status-dot" id="bambuDot"></span>B
+            </div>
+            <div class="status-item">
+                <span class="status-dot" id="spoolmanDot"></span>S
+            </div>
+            <div class="ram-status" id="ramStatus"></div>
+        </div>
+    </div>
+
+<!-- head -->
+
+<div class="connection-status hidden">
+    <div class="spinner"></div>
+    <span>Connection lost. Trying to reconnect...</span>
+</div>
+<div class="content">
+    <div class="three-column-layout">
+        <!-- Linke Spalte -->
+        <div class="column">
+            <div class="feature-box">
+                <div class="statistics-header">
+                    <h2>Statistics</h2>
+                    <button id="refreshSpoolman" class="refresh-button">
+                        <span>Refresh Spoolman</span>
+                    </button>
+                </div>
+                <div class="statistics-column">
+                    <h3>Spools</h3>
+                        <div class="spool-stat" style="display: flex; justify-content: center; align-items: center;">
+                            <span class="stat-label">total:</span>
+                            <span class="stat-value" id="totalSpools"></span>
+                            <div style="width: auto;"></div>
+                            <span class="stat-label">without Tag:</span>
+                            <span class="stat-value" id="spoolsWithoutTag"></span>
+                        </div>
+                </div>
+
+                <div class="statistics-grid">
+                    <div class="statistics-column">
+                        <h3>Overview</h3>
+                        <ul class="statistics-list">
+                            <li>
+                                <span class="stat-label">Manufacturer:</span>
+                                <span class="stat-value" id="totalVendors"></span>
+                            </li>
+                            <li>
+                                <span class="stat-label">Weight:</span>
+                                <span class="stat-value"><span id="totalWeight"></span></span>
+                            </li>
+                            <li>
+                                <span class="stat-label">Length:</span>
+                                <span class="stat-value"><span id="totalLength"></span></span>
+                            </li>
+                        </ul>
+                    </div>
+                    <div class="statistics-column">
+                        <h3>Materials</h3>
+                        <ul class="statistics-list" id="materialsList">
+                            <!-- Wird dynamisch befüllt -->
+                        </ul>
+                    </div>
+                </div>
+            </div>
+            <div class="feature-box">
+                <div class="nfc-header">
+                    <h2>NFC-Tag</h2>
+                    <span id="nfcStatusIndicator" class="status-circle"></span>
+                </div>
+                <div class="nfc-status-display"></div>
+            </div>
+        </div>
+
+        <!-- Mittlere Spalte -->
+        <div class="column">
+            <div class="feature-box">
+                <h2>Spoolman Spools</h2>
+                <label for="vendorSelect">Manufacturer:</label>
+                <div style="display: flex; justify-content: space-between; align-items: center;">
+                    <select id="vendorSelect" class="styled-select">
+                        <option value="">Please choose...</option>
+                    </select>
+                    <label style="margin-left: 10px;">
+                        <input type="checkbox" id="onlyWithoutSmId" checked onchange="updateFilamentDropdown()">
+                        Only Spools without SM ID
+                    </label>
+                </div>
+            </div>
+
+            <div id="filamentSection" class="feature-box hidden">
+                <label>Spool / Filament:</label>
+                <div class="custom-dropdown">
+                    <div class="dropdown-button" onclick="toggleFilamentDropdown()">
+                        <div class="selected-color" id="selected-color"></div>
+                        <span id="selected-filament">Please choose...</span>
+                        <span class="dropdown-arrow">▼</span>
+                    </div>
+                    <div class="dropdown-content" id="filament-dropdown-content">
+                        <!-- Optionen werden dynamisch hinzugefügt -->
+                    </div>
+                </div>
+                <p id="nfcInfo" class="nfc-status"></p>
+                <button id="writeNfcButton" class="btn btn-primary hidden" onclick="writeNfcTag()">Write Tag</button>
+            </div>
+        </div>
+
+        <!-- Rechte Spalte -->
+        <div class="column">
+            <div class="feature-box">
+                <h2>Bambu AMS</h2>
+                <div id="amsDataContainer">
+                    <div class="amsData" id="amsData">Wait for AMS-Data...</div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script src="spoolman.js"></script>
+<script src="rfid.js"></script>
+
+</body>
+</html>
diff --git a/src/bambu.cpp b/src/bambu.cpp
index f5f3752..4278c1e 100644
--- a/src/bambu.cpp
+++ b/src/bambu.cpp
@@ -27,6 +27,7 @@ const char* bambu_serialnr = nullptr;
 String g_bambu_ip = "";
 String g_bambu_accesscode = "";
 String g_bambu_serialnr = "";
+bool bambuDisabled = false;
 
 bool bambu_connected = false;
 bool autoSendToBambu = false;
@@ -654,10 +655,7 @@ bool setupMqtt() {
     } 
     else 
     {
-        Serial.println("Fehler: Keine MQTT-Daten vorhanden");
-        oledShowMessage("Bambu Credentials Missing");
-        oledShowTopRow();
-        vTaskDelay(2000 / portTICK_PERIOD_MS);
+        bambuDisabled = true;
         return false;
     }
     return true;
diff --git a/src/bambu.h b/src/bambu.h
index 1dc7b3d..1e8de4e 100644
--- a/src/bambu.h
+++ b/src/bambu.h
@@ -30,6 +30,7 @@ extern int ams_count;
 extern AMSData ams_data[MAX_AMS];
 extern bool autoSendToBambu;
 extern int autoSetToBambuSpoolId;
+extern bool bambuDisabled;
 
 bool loadBambuCredentials();
 bool saveBambuCredentials(const String& bambu_ip, const String& bambu_serialnr, const String& bambu_accesscode, const bool autoSend, const String& autoSendTime);
diff --git a/src/website.cpp b/src/website.cpp
index 2e01604..a49bdf8 100644
--- a/src/website.cpp
+++ b/src/website.cpp
@@ -29,7 +29,7 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
     if (type == WS_EVT_CONNECT) {
         Serial.println("Neuer Client verbunden!");
         // Sende die AMS-Daten an den neuen Client
-        sendAmsData(client);
+        if (!bambuDisabled) sendAmsData(client);
         sendNfcData(client);
         foundNfcTag(client, 0);
         sendWriteResult(client, 3);
@@ -213,7 +213,10 @@ void setupWebserver(AsyncWebServer &server) {
     // Route für RFID
     server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
         Serial.println("Anfrage für /rfid erhalten");
-        AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/rfid.html.gz", "text/html");
+        
+        String page = (bambuDisabled) ? "/rfid.html.gz" : "/rfid_bambu.html.gz";
+        AsyncWebServerResponse *response = request->beginResponse(LittleFS, page, "text/html");
+        
         response->addHeader("Content-Encoding", "gzip");
         response->addHeader("Cache-Control", CACHE_CONTROL);
         request->send(response);