Compare commits

...

11 Commits

Author SHA1 Message Date
tugsi 70c8b7bdc0 Delete data directory
Old and not used... Testing from SPIFFS
2025-03-16 19:40:05 +01:00
tugsi c574cc964e Merge branch 'Bambu-Serie-X-MQTT-Fix' of https://github.com/tugsi/Filaman into Bambu-Serie-X-MQTT-Fix 2025-03-16 19:35:08 +01:00
tugsi 9262865b56 - X1C MQTT Fix
- Spoolman Settings Fix
- Spoolman Out Fix
- Spoolman In Fix
2025-03-16 19:30:37 +01:00
tugsi f7c01eb5f0 Merge remote-tracking branch 'upstream/main' into Bambu-Serie-X-MQTT-Fix 2025-03-14 17:43:52 +01:00
tugsi a41ef9e75a docs: update changelog and header for version v1.4.1
- Die MQTT-Puffergröße auf 16.384 Byte (16 KB) erhöht.
Dies sollte ausreichen, um Ihre 15.403 Byte große JSON-Nutzlast mit etwas mehr Spielraum zu verarbeiten. Diese Änderung ermöglicht es dem MQTT-Client, größere JSON-Nachrichten ohne Kürzung zu empfangen und zu verarbeiten.

Einige wichtige Hinweise zu dieser Änderung:
Die neue Puffergröße von 16 KB verbraucht mehr RAM, der ESP32 sollte jedoch ausreichend Speicher dafür haben.
Die Größe ist auf 16 KB festgelegt, um über die benötigten 15.403 Byte hinaus zusätzlichen Puffer-Overhead bereitzustellen.

Diese Änderung betrifft nur den MQTT-Empfangspuffer
--
- Die Task-Stack-Größe von 8192 auf 16384 Wörter erhöht, um mehr Speicher für die JSON-Verarbeitung bereitzustellen
---
- Erhöhung des Keepalive-Intervalls auf 60 Sekunden
- Verbesserte Fehlerbehandlung und Debugging-Ausgaben
- Detaillierte Statusmeldungen für die MQTT-Verbindung
- Periodische Verbindungsüberprüfung alle 30 Sekunden
- Bessere Handhabung von Verbindungsverlusten
---
- Verwendung einer eindeutigen Client-ID mit Zufallssuffix
- Erhöhung der QoS (Quality of Service) auf 1 für zuverlässigere Übertragung
- Einstellung eines Socket-Timeouts von 60 Sekunden
- Aktivierung von Clean Session und Will Message
- Verbessertes Verbindungs-Logging
2025-03-14 17:42:26 +01:00
ManuelW 659dfb8627 Update README.de.md
Removed OpenSpool
2025-03-12 10:02:30 +01:00
ManuelW b4dd0d357a Update README.md 2025-03-12 10:01:40 +01:00
ManuelW 8e38a68191 Merge pull request #19 from tugsi/patch-1
Update README.de.md
2025-03-12 09:59:54 +01:00
ManuelW c3ec7edf6a Merge pull request #20 from tugsi/patch-2
Update README.md
2025-03-12 09:58:52 +01:00
tugsi a35e13e015 Update README.md
See German-Commit Readme :-)
2025-03-11 14:54:43 +01:00
tugsi e0df5d33f2 Update README.de.md
Einige Kleinigkeiten die mir aufgefallen sind.
- einheitlich Bambu Lab
- generell Namensgebung korrigiert
- die meisten Auflistungen haben ein . am Ende, eigentlich könnte man die weglassen, aber ich habe die, die keine hatten angepasst
- Installation Google Chrome oder Microsoft Edge hinzugefügt
2025-03-11 14:49:28 +01:00
6 changed files with 333 additions and 153 deletions
+5
View File
@@ -0,0 +1,5 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
+10
View File
@@ -0,0 +1,10 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}
+8 -9
View File
@@ -1,8 +1,8 @@
# FilaMan - Filament Management System
FilaMan ist ein Filament-Managementsystem für den 3D-Druck. Es verwendet ESP32-Hardware für Gewichtsmessungen und NFC-Tag-Management.
Benutzer können Filamentspulen verwalten, den Status des Automatic Material System (AMS) von Bablulab Druckern überwachen und Einstellungen über eine Weboberfläche vornehmen.
Das System integriert sich nahtlos mit der [Spoolman](https://github.com/Donkie/Spoolman) Filamentverwaltung, zusätzlich mit [Bambulab](https://bambulab.com/en-us) 3D-Druckern und sowie dem [Openspool](https://github.com/spuder/OpenSpool) NFC-TAG Format.
Benutzer können Filamentspulen verwalten, den Status des Automatic Material System (AMS) von Bambu Lab Druckern überwachen und Einstellungen über eine Weboberfläche vornehmen.
Das System integriert sich nahtlos mit der [Spoolman](https://github.com/Donkie/Spoolman) Filamentverwaltung, zusätzlich mit [Bambu Lab](https://bambulab.com/en-us) 3D-Druckern.
![Scale](./img/scale_trans.png)
@@ -16,18 +16,17 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v)
### ESP32 Hardware-Funktionen
- **Gewichtsmessung:** Verwendung einer Wägezelle mit HX711-Verstärker für präzise Gewichtsverfolgung.
- **NFC-Tag Lesen/Schreiben:** PN532-Modul zum Lesen und Schreiben von Filamentdaten auf NFC-Tags.
- **OLED-Display:** Zeigt aktuelles Gewicht, Verbindungsstatus (WiFi, Bambu Lab, Spoolman).
- **OLED-Display:** Zeigt aktuelles Gewicht, Verbindungsstatus (WiFi, BambuLab, Spoolman).
- **WLAN-Konnektivität:** WiFiManager für einfache Netzwerkkonfiguration.
- **MQTT-Integration:** Verbindet sich mit Bambu Lab Drucker für AMS-Steuerung.
- **NFC-Tag NTAG213 NTAG215:** Verwendung von NTAG213, besser NTAG215 wegen ausreichendem Speicherplatz auf dem Tag
- **NFC-Tag NTAG213 NTAG215:** Verwendung von NTAG213 (144 Bytes - Kapazität), besser NTAG215 (540 Bytes - Kapazität) wegen ausreichendem Speicherplatz auf dem Tag
### Weboberflächen-Funktionen
- **Echtzeit-Updates:** WebSocket-Verbindung für Live-Daten-Updates.
- **NFC-Tag-Verwaltung:**
- Filamentdaten auf NFC-Tags schreiben.
- Verwendet das NFC-Tag-Format von [Openspool](https://github.com/spuder/OpenSpool)
- Ermöglicht automatische Spulenerkennung im AMS
- **Bambulab AMS-Integration:**
- Ermöglicht automatische Spulenerkennung im AMS.
- **Bambu Lab AMS-Integration:**
- Anzeige der aktuellen AMS-Fachbelegung.
- Zuordnung von Filamenten zu AMS-Slots.
- Unterstützung für externe Spulenhalter.
@@ -36,7 +35,7 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v)
- Filtern und Auswählen von Filamenten.
- Automatische Aktualisierung der Spulengewichte.
- Verfolgung von NFC-Tag-Zuweisungen.
- Unterstützt das Spoolman Octoprint Plugin
- Unterstützt das Spoolman Octoprint Plugin.
### Wenn Sie meine Arbeit unterstützen möchten, freue ich mich über einen Kaffee
<a href="https://www.buymeacoffee.com/manuelw" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 30px !important;width: 108px !important;" ></a>
@@ -122,7 +121,7 @@ Du musst Spoolman auf DEBUG Modus setzten, da man bisher in Spoolman keine CORS
```
## Schritt-für-Schritt Installation
### Einfache Installation
### Einfache Installation (Google Chrome oder Microsoft Edge)
1. **Gehe auf [FilaMan Installer](https://www.filaman.app/installer.html)**
2. **Stecke dein ESP an den Rechner und klicke Connect**
+4 -5
View File
@@ -4,7 +4,7 @@
FilaMan is a filament management system for 3D printing. It uses ESP32 hardware for weight measurement and NFC tag management.
Users can manage filament spools, monitor the status of the Automatic Material System (AMS) and make settings via a web interface.
The system integrates seamlessly with [Bambulab](https://bambulab.com/en-us) 3D printers and [Spoolman](https://github.com/Donkie/Spoolman) filament management as well as the [Openspool](https://github.com/spuder/OpenSpool) NFC-TAG format.
The system integrates seamlessly with [Bambu Lab](https://bambulab.com/en-us) 3D printers and [Spoolman](https://github.com/Donkie/Spoolman) filament management.
![Scale](./img/scale_trans.png)
@@ -23,13 +23,12 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v)
- **OLED Display:** Shows current weight, connection status (WiFi, Bambu Lab, Spoolman).
- **WiFi Connectivity:** WiFiManager for easy network configuration.
- **MQTT Integration:** Connects to Bambu Lab printer for AMS control.
- **NFC-Tag NTAG213 NTAG215:** Use NTAG213, better NTAG215 because of enaught space on the Tag
- **NFC-Tag NTAG213 NTAG215:** Use NTAG213 (Capacity of 144 bytes), better NTAG215 (Capacity of 540 bytes) because of enaught space on the Tag.
### Web Interface Features
- **Real-time Updates:** WebSocket connection for live data updates.
- **NFC Tag Management:**
- Write filament data to NFC tags.
- uses NFC-Tag Format of [Openspool](https://github.com/spuder/OpenSpool)
- so you can use it with automatic Spool detection in AMS
- **Bambulab AMS Integration:**
- Display current AMS tray contents.
@@ -40,7 +39,7 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v)
- Filter and select filaments.
- Update spool weights automatically.
- Track NFC tag assignments.
- Supports Spoolman Octoprint Plugin
- Supports Spoolman Octoprint Plugin.
### If you want to support my work, i would be happy to get a coffe
<a href="https://www.buymeacoffee.com/manuelw" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 30px !important;width: 108px !important;" ></a>
@@ -128,7 +127,7 @@ You have to activate Spoolman in debug mode, because you are not able to set COR
## Step-by-Step Installation
### Easy Installation
### Easy Installation (Google Chrome or Microsoft Edge)
1. **Go to [FilaMan Installer](https://www.filaman.app/installer.html)**
2. **Plug you device in and push Connect button**
+147 -91
View File
@@ -53,7 +53,13 @@ function initWebSocket() {
// Wenn eine existierende Verbindung besteht, diese erst schließen
if (socket) {
try {
socket.onclose = null; // Remove onclose handler before closing
socket.onerror = null; // Remove error handler
socket.close();
} catch (e) {
console.error('Error closing existing socket:', e);
}
socket = null;
}
@@ -61,110 +67,80 @@ function initWebSocket() {
socket = new WebSocket('ws://' + window.location.host + '/ws');
socket.onopen = function() {
console.log('WebSocket connection established');
isConnected = true;
updateConnectionStatus();
startHeartbeat(); // Starte Heartbeat nach erfolgreicher Verbindung
};
socket.onclose = function() {
socket.onclose = function(event) {
console.log('WebSocket connection closed:', event.code, event.reason);
isConnected = false;
updateConnectionStatus();
if (heartbeatTimer) clearInterval(heartbeatTimer);
if (heartbeatTimer) {
clearInterval(heartbeatTimer);
heartbeatTimer = null;
}
// Nur neue Verbindung versuchen, wenn kein Timer läuft
if (!reconnectTimer) {
reconnectTimer = setTimeout(() => {
console.log('Attempting to reconnect...');
initWebSocket();
}, RECONNECT_INTERVAL);
}
};
socket.onerror = function(error) {
console.error('WebSocket error occurred:', error);
isConnected = false;
updateConnectionStatus();
if (heartbeatTimer) clearInterval(heartbeatTimer);
// Bei Fehler Verbindung schließen und neu aufbauen
if (socket) {
socket.close();
socket = null;
if (heartbeatTimer) {
clearInterval(heartbeatTimer);
heartbeatTimer = null;
}
};
socket.onmessage = function(event) {
lastHeartbeatResponse = Date.now(); // Aktualisiere Zeitstempel bei jeder Server-Antwort
try {
lastHeartbeatResponse = Date.now();
const data = JSON.parse(event.data);
if (data.type === 'amsData') {
displayAmsData(data.payload);
} else if (data.type === 'nfcTag') {
updateNfcStatusIndicator(data.payload);
} else if (data.type === 'nfcData') {
updateNfcData(data.payload);
} else if (data.type === 'writeNfcTag') {
handleWriteNfcTagResponse(data.success);
} else if (data.type === 'heartbeat') {
// Optional: Spezifische Behandlung von Heartbeat-Antworten
// Update status dots
const bambuDot = document.getElementById('bambuDot');
const spoolmanDot = document.getElementById('spoolmanDot');
const ramStatus = document.getElementById('ramStatus');
if (bambuDot) {
bambuDot.className = 'status-dot ' + (data.bambu_connected ? 'online' : 'offline');
// Add click handler only when offline
if (!data.bambu_connected) {
bambuDot.style.cursor = 'pointer';
bambuDot.onclick = function() {
if (socket && socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({
type: 'reconnect',
payload: 'bambu'
}));
}
};
} else {
bambuDot.style.cursor = 'default';
bambuDot.onclick = null;
}
}
if (spoolmanDot) {
spoolmanDot.className = 'status-dot ' + (data.spoolman_connected ? 'online' : 'offline');
// Add click handler only when offline
if (!data.spoolman_connected) {
spoolmanDot.style.cursor = 'pointer';
spoolmanDot.onclick = function() {
if (socket && socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({
type: 'reconnect',
payload: 'spoolman'
}));
}
};
} else {
spoolmanDot.style.cursor = 'default';
spoolmanDot.onclick = null;
}
}
if (ramStatus) {
ramStatus.textContent = `${data.freeHeap}k`;
}
}
else if (data.type === 'setSpoolmanSettings') {
if (data.payload == 'success') {
showNotification(`Spoolman Settings set successfully`, true);
} else {
showNotification(`Error setting Spoolman Settings`, false);
// Handle different message types
switch(data.type) {
case 'amsData':
displayAmsData(data.payload);
break;
case 'nfcTag':
updateNfcStatusIndicator(data.payload);
break;
case 'nfcData':
updateNfcData(data.payload);
break;
case 'writeNfcTag':
handleWriteNfcTagResponse(data.success);
break;
case 'heartbeat':
handleHeartbeatResponse(data);
break;
case 'setSpoolmanSettings':
handleSpoolmanSettingsResponse(data);
break;
default:
console.warn('Unknown message type:', data.type);
}
} catch (error) {
console.error('Error processing WebSocket message:', error);
}
};
} catch (error) {
console.error('Error initializing WebSocket:', error);
isConnected = false;
updateConnectionStatus();
// Nur neue Verbindung versuchen, wenn kein Timer läuft
if (!reconnectTimer) {
reconnectTimer = setTimeout(() => {
console.log('Attempting to reconnect after error...');
initWebSocket();
}, RECONNECT_INTERVAL);
}
@@ -389,6 +365,7 @@ function updateSpoolButtons(show) {
});
}
// Verbesserte Funktion zum Behandeln von Spoolman Settings
function handleSpoolmanSettings(tray_info_idx, setting_id, cali_idx, nozzle_temp_min, nozzle_temp_max) {
// Hole das ausgewählte Filament
const selectedText = document.getElementById("selected-filament").textContent;
@@ -419,6 +396,7 @@ function handleSpoolmanSettings(tray_info_idx, setting_id, cali_idx, nozzle_temp
}
}
// Verbesserte Funktion zum Behandeln von Spool Out
function handleSpoolOut() {
// Erstelle Payload
const payload = {
@@ -443,17 +421,21 @@ function handleSpoolOut() {
}
}
// Neue Funktion zum Behandeln des Spool-In-Klicks
// Verbesserte Funktion zum Behandeln des Spool-In-Klicks
function handleSpoolIn(amsId, trayId) {
console.log("handleSpoolIn called with amsId:", amsId, "trayId:", trayId);
// Prüfe WebSocket Verbindung zuerst
if (!socket || socket.readyState !== WebSocket.OPEN) {
showNotification("No active WebSocket connection!", false);
console.error("WebSocket not connected");
console.error("WebSocket not connected, state:", socket ? socket.readyState : "no socket");
return;
}
// Hole das ausgewählte Filament
const selectedText = document.getElementById("selected-filament").textContent;
console.log("Selected filament:", selectedText);
if (selectedText === "Please choose...") {
showNotification("Choose Filament first", false);
return;
@@ -466,53 +448,55 @@ function handleSpoolIn(amsId, trayId) {
if (!selectedSpool) {
showNotification("Selected Spool not found", false);
console.error("Selected spool not found in spoolsData");
return;
}
console.log("Found spool data:", selectedSpool);
// Temperaturwerte extrahieren
let minTemp = "175";
let maxTemp = "275";
if (Array.isArray(selectedSpool.filament.nozzle_temperature) &&
if (selectedSpool.filament &&
Array.isArray(selectedSpool.filament.nozzle_temperature) &&
selectedSpool.filament.nozzle_temperature.length >= 2) {
minTemp = selectedSpool.filament.nozzle_temperature[0];
maxTemp = selectedSpool.filament.nozzle_temperature[1];
}
// Extrahiere bambu_idx
let bambuIdx = "GFL99"; // Default zu Generic PLA
if (selectedSpool.filament?.extra?.bambu_idx) {
bambuIdx = selectedSpool.filament.extra.bambu_idx.replace(/['"]/g, '');
} else if (selectedSpool.extra?.bambu_idx) {
bambuIdx = selectedSpool.extra.bambu_idx.replace(/['"]/g, '');
}
// Erstelle Payload
const payload = {
type: 'setBambuSpool',
payload: {
amsId: amsId,
trayId: trayId,
color: selectedSpool.filament.color_hex || "FFFFFF",
color: selectedSpool.filament && selectedSpool.filament.color_hex ? selectedSpool.filament.color_hex : "FFFFFF",
nozzle_temp_min: parseInt(minTemp),
nozzle_temp_max: parseInt(maxTemp),
type: selectedSpool.filament.material,
brand: selectedSpool.filament.vendor.name,
tray_info_idx: selectedSpool.filament.extra.bambu_idx.replace(/['"]+/g, '').trim(),
type: selectedSpool.filament && selectedSpool.filament.material ? selectedSpool.filament.material : "PLA",
brand: selectedSpool.filament && selectedSpool.filament.vendor ? selectedSpool.filament.vendor.name : "",
tray_info_idx: bambuIdx,
cali_idx: "-1" // Default-Wert setzen
}
};
// Prüfe, ob der Key cali_idx vorhanden ist und setze ihn
if (selectedSpool.filament.extra.bambu_cali_id) {
payload.payload.cali_idx = selectedSpool.filament.extra.bambu_cali_id.replace(/['"]+/g, '').trim();
}
// Prüfe, ob der Key bambu_setting_id vorhanden ist
if (selectedSpool.filament.extra.bambu_setting_id) {
payload.payload.bambu_setting_id = selectedSpool.filament.extra.bambu_setting_id.replace(/['"]+/g, '').trim();
}
console.log("Spool-In Payload:", payload);
console.log("Sending payload:", payload);
try {
socket.send(JSON.stringify(payload));
showNotification(`Spool set in AMS ${amsId} Tray ${trayId}. Pls wait`, true);
showNotification(`Spool settings sent to printer. Please wait...`, true);
} catch (error) {
console.error("Fehler beim Senden der WebSocket Nachricht:", error);
showNotification("Error while sending", false);
console.error("Error sending WebSocket message:", error);
showNotification("Error sending spool settings!", false);
}
}
@@ -687,3 +671,75 @@ function showNotification(message, isSuccess) {
}, 300);
}, 3000);
}
// Neue Handler-Funktionen für bessere Modularität
function handleHeartbeatResponse(data) {
const bambuDot = document.getElementById('bambuDot');
const spoolmanDot = document.getElementById('spoolmanDot');
const ramStatus = document.getElementById('ramStatus');
if (bambuDot) {
bambuDot.className = 'status-dot ' + (data.bambu_connected ? 'online' : 'offline');
if (!data.bambu_connected) {
bambuDot.style.cursor = 'pointer';
bambuDot.onclick = function() {
sendReconnectRequest('bambu');
};
} else {
bambuDot.style.cursor = 'default';
bambuDot.onclick = null;
}
}
if (spoolmanDot) {
spoolmanDot.className = 'status-dot ' + (data.spoolman_connected ? 'online' : 'offline');
if (!data.spoolman_connected) {
spoolmanDot.style.cursor = 'pointer';
spoolmanDot.onclick = function() {
sendReconnectRequest('spoolman');
};
} else {
spoolmanDot.style.cursor = 'default';
spoolmanDot.onclick = null;
}
}
if (ramStatus) {
ramStatus.textContent = `${data.freeHeap}k`;
}
}
function handleSpoolmanSettingsResponse(data) {
if (data.payload === 'success') {
showNotification(`Spoolman Settings set successfully`, true);
} else {
showNotification(`Error setting Spoolman Settings`, false);
}
}
function sendReconnectRequest(target) {
if (socket?.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({
type: 'reconnect',
payload: target
}));
}
}
// Verbesserte Funktion zum Senden von WebSocket-Nachrichten
function sendWebSocketMessage(message) {
if (!socket || socket.readyState !== WebSocket.OPEN) {
console.error('WebSocket is not connected');
showNotification("Connection error - please try again", false);
return;
}
try {
const jsonString = JSON.stringify(message);
console.log('Sending WebSocket message:', jsonString);
socket.send(jsonString);
} catch (error) {
console.error('Error sending WebSocket message:', error);
showNotification("Error sending message", false);
}
}
+153 -42
View File
@@ -18,7 +18,7 @@ PubSubClient client(sslClient);
TaskHandle_t BambuMqttTask;
String report_topic = "";
//String request_topic = "";
String request_topic = "";
const char* bambu_username = "bblp";
const char* bambu_ip = nullptr;
const char* bambu_accesscode = nullptr;
@@ -92,7 +92,7 @@ bool loadBambuCredentials() {
bambu_serialnr = g_bambu_serialnr.c_str();
report_topic = "device/" + String(bambu_serialnr) + "/report";
//request_topic = "device/" + String(bambu_serialnr) + "/request";
request_topic = "device/" + String(bambu_serialnr) + "/request";
return true;
}
Serial.println("Keine gültigen Bambu-Credentials gefunden.");
@@ -197,18 +197,69 @@ FilamentResult findFilamentIdx(String brand, String type) {
}
bool sendMqttMessage(const String& payload) {
Serial.println("Sending MQTT message");
Serial.println(payload);
if (client.publish(report_topic.c_str(), payload.c_str()))
{
return true;
// Check MQTT client state first
if (!client.connected()) {
Serial.println("Error: MQTT client not connected when trying to send message");
Serial.print("MQTT client state: ");
Serial.println(client.state());
return false;
}
// Check if request_topic is empty
if (request_topic.isEmpty()) {
Serial.println("Error: request_topic is empty!");
return false;
}
// Check payload
if (payload.isEmpty()) {
Serial.println("Error: Empty payload!");
return false;
}
Serial.println("Attempting to send MQTT message:");
Serial.println("Topic: " + request_topic);
Serial.println("Payload: " + payload);
Serial.println("Payload length: " + String(payload.length()));
// Try to publish with QoS 1 and retain flag false
bool published = client.publish(request_topic.c_str(), payload.c_str(), false);
if (published) {
Serial.println("MQTT message published successfully");
return true;
} else {
Serial.println("Failed to publish MQTT message");
Serial.print("MQTT client state after publish attempt: ");
Serial.println(client.state());
// Additional error information
switch(client.state()) {
case -4:
Serial.println("Reason: Connection timeout");
break;
case -3:
Serial.println("Reason: Connection lost");
break;
case -2:
Serial.println("Reason: Connect failed");
break;
case -1:
Serial.println("Reason: Disconnected");
break;
case 0:
Serial.println("Reason: Connected but publish failed");
break;
default:
Serial.println("Reason: Unknown error");
break;
}
return false;
}
}
bool setBambuSpool(String payload) {
Serial.println("Spool settings in");
Serial.println("Spool settings received from WebSocket");
Serial.println(payload);
// Parse the JSON
@@ -220,21 +271,28 @@ bool setBambuSpool(String payload) {
return false;
}
int amsId = doc["amsId"];
int trayId = doc["trayId"];
// Check if we have all required fields
if (!doc["amsId"].is<int>() || !doc["trayId"].is<int>()) {
Serial.println("Error: Missing or invalid required fields in payload");
return false;
}
int amsId = doc["amsId"].as<int>();
int trayId = doc["trayId"].as<int>();
String color = doc["color"].as<String>();
color.toUpperCase();
int minTemp = doc["nozzle_temp_min"];
int maxTemp = doc["nozzle_temp_max"];
String type = doc["type"].as<String>();
int minTemp = doc["nozzle_temp_min"] | 0; // Default to 0 if not present
int maxTemp = doc["nozzle_temp_max"] | 0; // Default to 0 if not present
String type = doc["type"] | ""; // Default to empty string if not present
(type == "PLA+") ? type = "PLA" : type;
String brand = doc["brand"].as<String>();
String brand = doc["brand"] | ""; // Default to empty string if not present
String tray_info_idx = (doc["tray_info_idx"].as<String>() != "-1") ? doc["tray_info_idx"].as<String>() : "";
if (tray_info_idx == "") {
if (brand != "" && type != "") {
FilamentResult result = findFilamentIdx(brand, type);
tray_info_idx = result.key;
type = result.type; // Aktualisiere den type mit dem gefundenen Basistyp
Serial.println("Found filament idx: " + tray_info_idx + " for type: " + type);
}
}
String setting_id = doc["bambu_setting_id"].as<String>();
@@ -242,6 +300,7 @@ bool setBambuSpool(String payload) {
doc.clear();
// Create MQTT message
doc["print"]["sequence_id"] = "0";
doc["print"]["command"] = "ams_filament_setting";
doc["print"]["ams_id"] = amsId < 200 ? amsId : 255;
@@ -250,26 +309,25 @@ bool setBambuSpool(String payload) {
doc["print"]["nozzle_temp_min"] = minTemp;
doc["print"]["nozzle_temp_max"] = maxTemp;
doc["print"]["tray_type"] = type;
//doc["print"]["cali_idx"] = (cali_idx != "") ? cali_idx : "";
doc["print"]["tray_info_idx"] = tray_info_idx;
doc["print"]["setting_id"] = setting_id;
// Serialize the JSON
// Serialize and send MQTT message
String output;
serializeJson(doc, output);
Serial.println("Sending to Bambu printer:");
Serial.println(output);
if (sendMqttMessage(output)) {
Serial.println("Spool successfully set");
}
else
{
Serial.println("Failed to set spool");
if (!sendMqttMessage(output)) {
Serial.println("Failed to send filament settings to printer");
return false;
}
Serial.println("Filament settings sent successfully");
doc.clear();
yield();
// Send calibration if available
if (cali_idx != "") {
yield();
doc["print"]["sequence_id"] = "0";
@@ -278,21 +336,18 @@ bool setBambuSpool(String payload) {
doc["print"]["nozzle_diameter"] = "0.4";
doc["print"]["cali_idx"] = cali_idx.toInt();
doc["print"]["tray_id"] = trayId < 200 ? trayId : 254;
//doc["print"]["ams_id"] = amsId < 200 ? amsId : 255;
// Serialize the JSON
String output;
serializeJson(doc, output);
Serial.println("Sending calibration to printer:");
Serial.println(output);
if (sendMqttMessage(output)) {
Serial.println("Extrusion calibration successfully set");
}
else
{
Serial.println("Failed to set extrusion calibration");
if (!sendMqttMessage(output)) {
Serial.println("Failed to send calibration settings to printer");
return false;
}
Serial.println("Calibration settings sent successfully");
doc.clear();
yield();
}
@@ -549,20 +604,47 @@ void reconnect() {
uint8_t retries = 0;
while (!client.connected()) {
Serial.println("Attempting MQTT re/connection...");
Serial.print("State before connect: ");
Serial.println(client.state());
bambu_connected = false;
oledShowTopRow();
// Attempt to connect
if (client.connect(bambu_serialnr, bambu_username, bambu_accesscode)) {
// Generate a random client ID suffix
String clientId = String(bambu_serialnr) + "_" + String(random(0xffff), HEX);
Serial.print("Reconnecting with client ID: ");
Serial.println(clientId);
// Attempt to connect with clean session and will message
if (client.connect(clientId.c_str(), bambu_username, bambu_accesscode, nullptr, 0, true, nullptr)) {
Serial.println("MQTT re/connected");
client.subscribe(report_topic.c_str());
// Subscribe with QoS 1
if (client.subscribe(report_topic.c_str(), 1)) {
Serial.println("Successfully subscribed to topic with QoS 1: " + report_topic);
} else {
Serial.println("Failed to subscribe to topic: " + report_topic);
}
bambu_connected = true;
oledShowTopRow();
} else {
int state = client.state();
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
Serial.print(state);
Serial.print(" (");
// Print detailed error message
switch(state) {
case -4: Serial.print("MQTT_CONNECTION_TIMEOUT"); break;
case -3: Serial.print("MQTT_CONNECTION_LOST"); break;
case -2: Serial.print("MQTT_CONNECT_FAILED"); break;
case -1: Serial.print("MQTT_DISCONNECTED"); break;
case 1: Serial.print("MQTT_CONNECT_BAD_PROTOCOL"); break;
case 2: Serial.print("MQTT_CONNECT_BAD_CLIENT_ID"); break;
case 3: Serial.print("MQTT_CONNECT_UNAVAILABLE"); break;
case 4: Serial.print("MQTT_CONNECT_BAD_CREDENTIALS"); break;
case 5: Serial.print("MQTT_CONNECT_UNAUTHORIZED"); break;
default: Serial.print("UNKNOWN"); break;
}
Serial.println(") try again in 5 seconds");
bambu_connected = false;
oledShowTopRow();
@@ -570,11 +652,9 @@ void reconnect() {
vTaskDelay(5000 / portTICK_PERIOD_MS);
if (retries > 5) {
Serial.println("Disable Bambu MQTT Task after 5 retries");
//vTaskSuspend(BambuMqttTask);
vTaskDelete(BambuMqttTask);
break;
}
retries++;
}
}
@@ -582,17 +662,32 @@ void reconnect() {
void mqtt_loop(void * parameter) {
Serial.println("Bambu MQTT Task gestartet");
unsigned long lastCheck = 0;
for(;;) {
if (pauseBambuMqttTask) {
vTaskDelay(10000);
continue;
}
unsigned long now = millis();
if (!client.connected()) {
Serial.println("Connection lost, attempting reconnect...");
reconnect();
yield();
esp_task_wdt_reset();
vTaskDelay(100);
continue;
}
// Periodically check connection status
if (now - lastCheck > 30000) { // Check every 30 seconds
Serial.print("MQTT Status Check - Connected: ");
Serial.println(client.connected() ? "Yes" : "No");
lastCheck = now;
}
client.loop();
yield();
esp_task_wdt_reset();
@@ -617,14 +712,30 @@ bool setupMqtt() {
sslClient.setInsecure();
client.setServer(bambu_ip, 8883);
// Generate a random client ID suffix
String clientId = String(bambu_serialnr) + "_" + String(random(0xffff), HEX);
// MQTT Connection Options
client.setKeepAlive(60);
client.setSocketTimeout(60); // Increase socket timeout
Serial.print("Connecting with client ID: ");
Serial.println(clientId);
// Verbinden mit dem MQTT-Server
bool connected = true;
if (client.connect(bambu_serialnr, bambu_username, bambu_accesscode))
if (client.connect(clientId.c_str(), bambu_username, bambu_accesscode, nullptr, 0, true, nullptr))
{
client.setCallback(mqtt_callback);
client.setBufferSize(5120);
client.subscribe(report_topic.c_str());
//client.subscribe(request_topic.c_str());
client.setBufferSize(16384); // Increased to 16KB to handle larger JSON
// Subscribe with QoS 1
if (client.subscribe(report_topic.c_str(), 1)) {
Serial.println("Successfully subscribed to topic with QoS 1: " + report_topic);
} else {
Serial.println("Failed to subscribe to topic: " + report_topic);
}
Serial.println("MQTT-Client initialisiert");
oledShowMessage("Bambu Connected");
@@ -634,7 +745,7 @@ bool setupMqtt() {
xTaskCreatePinnedToCore(
mqtt_loop, /* Function to implement the task */
"BambuMqtt", /* Name of the task */
8192, /* Stack size in words */
16384, /* Stack size in words */
NULL, /* Task input parameter */
mqttTaskPrio, /* Priority of the task */
&BambuMqttTask, /* Task handle. */