Compare commits

...

10 Commits

Author SHA1 Message Date
tugsi f1a9c3c5d4 -Abfrage Error gefixt, wenn leer dann kein Error mehr 2025-03-17 11:19:28 +01:00
tugsi ccca159a10 rfid.js wieder auf Originalstand gebracht 2025-03-17 09:31:26 +01:00
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
Manuel Weiser 3eac0e5ac4 update Discord Link 2025-03-15 16:02:18 +01:00
Manuel Weiser 24d91693d9 update Discord Link 2025-03-15 15:57:46 +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
Manuel Weiser 94c26590c8 remove commented-out subscription topic in MQTT setup 2025-03-10 17:41:14 +01:00
6 changed files with 227 additions and 102 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"
]
}
+1 -1
View File
@@ -9,7 +9,7 @@ Das System integriert sich nahtlos mit der [Spoolman](https://github.com/Donkie/
Weitere Bilder finden Sie im [img Ordner](/img/)
oder auf meiner Website: [FilaMan Website](https://www.filaman.app)
Deutsches Erklärvideo: [Youtube](https://youtu.be/uNDe2wh9SS8?si=b-jYx4I1w62zaOHU)
Discord Server: [https://discord.gg/vMAx2gf5](https://discord.gg/vMAx2gf5)
Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v)
### Es gibt jetzt auch ein Wiki, dort sind nochmal alle Funktionen beschrieben: [Wiki](https://github.com/ManuelW77/Filaman/wiki)
+1 -1
View File
@@ -13,7 +13,7 @@ The system integrates seamlessly with [Bambu Lab](https://bambulab.com/en-us) 3D
More Images can be found in the [img Folder](/img/)
or my website: [FilaMan Website](https://www.filaman.app)
german explanatory video: [Youtube](https://youtu.be/uNDe2wh9SS8?si=b-jYx4I1w62zaOHU)
Discord Server: [https://discord.gg/vMAx2gf5](https://discord.gg/vMAx2gf5)
Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v)
### Now more detailed informations about the usage: [Wiki](https://github.com/ManuelW77/Filaman/wiki)
+55 -55
View File
@@ -11,7 +11,7 @@ let reconnectTimer = null;
// WebSocket Funktionen
function startHeartbeat() {
if (heartbeatTimer) clearInterval(heartbeatTimer);
heartbeatTimer = setInterval(() => {
// Prüfe ob zu lange keine Antwort kam
if (Date.now() - lastHeartbeatResponse > HEARTBEAT_TIMEOUT) {
@@ -29,7 +29,7 @@ function startHeartbeat() {
updateConnectionStatus();
return;
}
try {
// Sende Heartbeat
socket.send(JSON.stringify({ type: 'heartbeat' }));
@@ -59,18 +59,18 @@ function initWebSocket() {
try {
socket = new WebSocket('ws://' + window.location.host + '/ws');
socket.onopen = function() {
socket.onopen = function () {
isConnected = true;
updateConnectionStatus();
startHeartbeat(); // Starte Heartbeat nach erfolgreicher Verbindung
};
socket.onclose = function() {
socket.onclose = function () {
isConnected = false;
updateConnectionStatus();
if (heartbeatTimer) clearInterval(heartbeatTimer);
// Nur neue Verbindung versuchen, wenn kein Timer läuft
if (!reconnectTimer) {
reconnectTimer = setTimeout(() => {
@@ -78,22 +78,22 @@ function initWebSocket() {
}, RECONNECT_INTERVAL);
}
};
socket.onerror = function(error) {
socket.onerror = function (error) {
isConnected = false;
updateConnectionStatus();
if (heartbeatTimer) clearInterval(heartbeatTimer);
// Bei Fehler Verbindung schließen und neu aufbauen
if (socket) {
socket.close();
socket = null;
}
};
socket.onmessage = function(event) {
socket.onmessage = function (event) {
lastHeartbeatResponse = Date.now(); // Aktualisiere Zeitstempel bei jeder Server-Antwort
const data = JSON.parse(event.data);
if (data.type === 'amsData') {
displayAmsData(data.payload);
@@ -109,13 +109,13 @@ function initWebSocket() {
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() {
bambuDot.onclick = function () {
if (socket && socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({
type: 'reconnect',
@@ -133,7 +133,7 @@ function initWebSocket() {
// Add click handler only when offline
if (!data.spoolman_connected) {
spoolmanDot.style.cursor = 'pointer';
spoolmanDot.onclick = function() {
spoolmanDot.onclick = function () {
if (socket && socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({
type: 'reconnect',
@@ -161,7 +161,7 @@ function initWebSocket() {
} catch (error) {
isConnected = false;
updateConnectionStatus();
// Nur neue Verbindung versuchen, wenn kein Timer läuft
if (!reconnectTimer) {
reconnectTimer = setTimeout(() => {
@@ -189,26 +189,26 @@ function updateConnectionStatus() {
}
// Event Listeners
document.addEventListener("DOMContentLoaded", function() {
document.addEventListener("DOMContentLoaded", function () {
initWebSocket();
// Event Listener für Checkbox
document.getElementById("onlyWithoutSmId").addEventListener("change", function() {
document.getElementById("onlyWithoutSmId").addEventListener("change", function () {
const spoolsData = window.getSpoolData();
window.populateVendorDropdown(spoolsData);
});
});
// Event Listener für Spoolman Events
document.addEventListener('spoolDataLoaded', function(event) {
document.addEventListener('spoolDataLoaded', function (event) {
window.populateVendorDropdown(event.detail);
});
document.addEventListener('spoolmanError', function(event) {
document.addEventListener('spoolmanError', function (event) {
showNotification(`Spoolman Error: ${event.detail.message}`, false);
});
document.addEventListener('filamentSelected', function(event) {
document.addEventListener('filamentSelected', function (event) {
updateNfcInfo();
// Zeige Spool-Buttons wenn ein Filament ausgewählt wurde
const selectedText = document.getElementById("selected-filament").textContent;
@@ -218,13 +218,13 @@ document.addEventListener('filamentSelected', function(event) {
// Hilfsfunktion für kontrastreiche Textfarbe
function getContrastColor(hexcolor) {
// Konvertiere Hex zu RGB
const r = parseInt(hexcolor.substr(0,2),16);
const g = parseInt(hexcolor.substr(2,2),16);
const b = parseInt(hexcolor.substr(4,2),16);
const r = parseInt(hexcolor.substr(0, 2), 16);
const g = parseInt(hexcolor.substr(2, 2), 16);
const b = parseInt(hexcolor.substr(4, 2), 16);
// Berechne Helligkeit (YIQ Formel)
const yiq = ((r*299)+(g*587)+(b*114))/1000;
const yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
// Return schwarz oder weiß basierend auf Helligkeit
return (yiq >= 128) ? '#000000' : '#FFFFFF';
}
@@ -242,7 +242,7 @@ function updateNfcInfo() {
}
// Finde die ausgewählte Spule in den Daten
const selectedSpool = spoolsData.find(spool =>
const selectedSpool = spoolsData.find(spool =>
`${spool.id} | ${spool.filament.name} (${spool.filament.material})` === selectedText
);
@@ -255,18 +255,18 @@ function updateNfcInfo() {
function displayAmsData(amsData) {
const amsDataContainer = document.getElementById('amsData');
amsDataContainer.innerHTML = '';
amsDataContainer.innerHTML = '';
amsData.forEach((ams) => {
// Bestimme den Anzeigenamen für das AMS
const amsDisplayName = ams.ams_id === 255 ? 'External Spool' : `AMS ${ams.ams_id}`;
const trayHTML = ams.tray.map(tray => {
// Prüfe ob überhaupt Daten vorhanden sind
const relevantFields = ['tray_type', 'tray_sub_brands', 'tray_info_idx', 'setting_id', 'cali_idx'];
const hasAnyContent = relevantFields.some(field =>
tray[field] !== null &&
tray[field] !== undefined &&
const hasAnyContent = relevantFields.some(field =>
tray[field] !== null &&
tray[field] !== undefined &&
tray[field] !== '' &&
tray[field] !== 'null'
);
@@ -282,8 +282,8 @@ function displayAmsData(amsData) {
cursor: pointer; display: none;">
<img src="spool_in.png" alt="Spool In" style="width: 48px; height: 48px;">
</button>`;
// Nur für nicht-leere Trays den Button-HTML erstellen
// Nur für nicht-leere Trays den Button-HTML erstellen
const outButtonHtml = `
<button class="spool-button" onclick="handleSpoolOut()"
style="position: absolute; top: -35px; right: -15px;
@@ -313,7 +313,7 @@ function displayAmsData(amsData) {
}
// Generiere den Type mit Color-Box zusammen
const typeWithColor = tray.tray_type ?
const typeWithColor = tray.tray_type ?
`<p>Typ: ${tray.tray_type} ${tray.tray_color ? `<span style="
background-color: #${tray.tray_color};
width: 20px;
@@ -334,9 +334,9 @@ function displayAmsData(amsData) {
// Nur gültige Felder anzeigen
const trayDetails = trayProperties
.filter(prop =>
tray[prop.key] !== null &&
tray[prop.key] !== undefined &&
.filter(prop =>
tray[prop.key] !== null &&
tray[prop.key] !== undefined &&
tray[prop.key] !== '' &&
tray[prop.key] !== 'null'
)
@@ -350,7 +350,7 @@ function displayAmsData(amsData) {
.join('');
// Temperaturen nur anzeigen, wenn beide nicht 0 sind
const tempHTML = (tray.nozzle_temp_min > 0 && tray.nozzle_temp_max > 0)
const tempHTML = (tray.nozzle_temp_min > 0 && tray.nozzle_temp_max > 0)
? `<p>Nozzle Temp: ${tray.nozzle_temp_min}°C - ${tray.nozzle_temp_max}°C</p>`
: '';
@@ -376,7 +376,7 @@ function displayAmsData(amsData) {
${trayHTML}
</div>
</div>`;
amsDataContainer.innerHTML += amsInfo;
});
}
@@ -394,7 +394,7 @@ function handleSpoolmanSettings(tray_info_idx, setting_id, cali_idx, nozzle_temp
const selectedText = document.getElementById("selected-filament").textContent;
// Finde die ausgewählte Spule in den Daten
const selectedSpool = spoolsData.find(spool =>
const selectedSpool = spoolsData.find(spool =>
`${spool.id} | ${spool.filament.name} (${spool.filament.material})` === selectedText
);
@@ -460,7 +460,7 @@ function handleSpoolIn(amsId, trayId) {
}
// Finde die ausgewählte Spule in den Daten
const selectedSpool = spoolsData.find(spool =>
const selectedSpool = spoolsData.find(spool =>
`${spool.id} | ${spool.filament.name} (${spool.filament.material})` === selectedText
);
@@ -473,7 +473,7 @@ function handleSpoolIn(amsId, trayId) {
let minTemp = "175";
let maxTemp = "275";
if (Array.isArray(selectedSpool.filament.nozzle_temperature) &&
if (Array.isArray(selectedSpool.filament.nozzle_temperature) &&
selectedSpool.filament.nozzle_temperature.length >= 2) {
minTemp = selectedSpool.filament.nozzle_temperature[0];
maxTemp = selectedSpool.filament.nozzle_temperature[1];
@@ -490,7 +490,7 @@ function handleSpoolIn(amsId, trayId) {
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(),
tray_info_idx: selectedSpool.filament.extra.bambu_idx?.replace(/['"]+/g, '').trim() || '',
cali_idx: "-1" // Default-Wert setzen
}
};
@@ -518,7 +518,7 @@ function handleSpoolIn(amsId, trayId) {
function updateNfcStatusIndicator(data) {
const indicator = document.getElementById('nfcStatusIndicator');
if (data.found === 0) {
// Kein NFC Tag gefunden
indicator.className = 'status-circle';
@@ -534,7 +534,7 @@ function updateNfcStatusIndicator(data) {
function updateNfcData(data) {
// Den Container für den NFC Status finden
const nfcStatusContainer = document.querySelector('.nfc-status-display');
// Bestehende Daten-Anzeige entfernen falls vorhanden
const existingData = nfcStatusContainer.querySelector('.nfc-data');
if (existingData) {
@@ -593,7 +593,7 @@ function updateNfcData(data) {
if (matchingSpool) {
// Zuerst Hersteller-Dropdown aktualisieren
document.getElementById("vendorSelect").value = matchingSpool.filament.vendor.id;
// Dann Filament-Dropdown aktualisieren und Spule auswählen
updateFilamentDropdown();
setTimeout(() => {
@@ -606,7 +606,7 @@ function updateNfcData(data) {
html += '</div>';
nfcDataDiv.innerHTML = html;
// Neues div zum Container hinzufügen
nfcStatusContainer.appendChild(nfcDataDiv);
}
@@ -619,7 +619,7 @@ function writeNfcTag() {
}
const spoolsData = window.getSpoolData();
const selectedSpool = spoolsData.find(spool =>
const selectedSpool = spoolsData.find(spool =>
`${spool.id} | ${spool.filament.name} (${spool.filament.material})` === selectedText
);
@@ -631,8 +631,8 @@ function writeNfcTag() {
// Temperaturwerte korrekt extrahieren
let minTemp = "175";
let maxTemp = "275";
if (Array.isArray(selectedSpool.filament.nozzle_temperature) &&
if (Array.isArray(selectedSpool.filament.nozzle_temperature) &&
selectedSpool.filament.nozzle_temperature.length >= 2) {
minTemp = String(selectedSpool.filament.nozzle_temperature[0]);
maxTemp = String(selectedSpool.filament.nozzle_temperature[1]);
@@ -686,4 +686,4 @@ function showNotification(message, isSuccess) {
notification.remove();
}, 300);
}, 3000);
}
}
+155 -45
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()));
return false;
// 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)) {
Serial.println("MQTT re/connected");
// Generate a random client ID suffix
String clientId = String(bambu_serialnr) + "_" + String(random(0xffff), HEX);
Serial.print("Reconnecting with client ID: ");
Serial.println(clientId);
client.subscribe(report_topic.c_str());
// 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");
// 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,15 +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);
// Optional: Topic abonnieren
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");
@@ -635,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. */