Compare commits

..

6 Commits

Author SHA1 Message Date
tugsi e5e3dcba8c gitignore 2025-03-23 17:51:09 +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
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
27 changed files with 447 additions and 927 deletions
+4
View File
@@ -1,3 +1,7 @@
.pio
.vscode
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
data
+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"
]
}
+9
View File
@@ -141,6 +141,15 @@
</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>
+198 -141
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' }));
@@ -53,118 +53,94 @@ function initWebSocket() {
// Wenn eine existierende Verbindung besteht, diese erst schließen
if (socket) {
socket.close();
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;
}
try {
socket = new WebSocket('ws://' + window.location.host + '/ws');
socket.onopen = function () {
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) {
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
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);
socket.onmessage = function(event) {
try {
lastHeartbeatResponse = Date.now();
const data = JSON.parse(event.data);
// 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);
}
@@ -189,26 +165,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 +194,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 +218,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 +231,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 +258,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 +289,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 +310,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 +326,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 +352,7 @@ function displayAmsData(amsData) {
${trayHTML}
</div>
</div>`;
amsDataContainer.innerHTML += amsInfo;
});
}
@@ -389,12 +365,13 @@ 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;
// 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
);
@@ -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,82 +421,88 @@ 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;
}
// 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
);
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);
}
}
function updateNfcStatusIndicator(data) {
const indicator = document.getElementById('nfcStatusIndicator');
if (data.found === 0) {
// Kein NFC Tag gefunden
indicator.className = 'status-circle';
@@ -534,7 +518,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 +577,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 +590,7 @@ function updateNfcData(data) {
html += '</div>';
nfcDataDiv.innerHTML = html;
// Neues div zum Container hinzufügen
nfcStatusContainer.appendChild(nfcDataDiv);
}
@@ -619,7 +603,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 +615,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]);
@@ -685,4 +669,77 @@ function showNotification(message, isSuccess) {
setTimeout(() => {
notification.remove();
}, 300);
}, 3000);}
}, 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);
}
}
-165
View File
@@ -1,165 +0,0 @@
<!-- 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>
+2 -33
View File
@@ -57,31 +57,6 @@
toggleOctoFields();
};
function removeBambuCredentials() {
fetch('/api/bambu?remove=true')
.then(response => response.json())
.then(data => {
if (data.success) {
document.getElementById('bambuIp').value = '';
document.getElementById('bambuSerial').value = '';
document.getElementById('bambuCode').value = '';
document.getElementById('autoSend').checked = false;
document.getElementById('autoSendTime').value = '';
document.getElementById('bambuStatusMessage').innerText = 'Bambu Credentials removed!';
// Reload with forced cache refresh after short delay
setTimeout(() => {
window.location.reload(true);
window.location.href = '/';
}, 1500);
} else {
document.getElementById('bambuStatusMessage').innerText = 'Error while removing Bambu Credentials.';
}
})
.catch(error => {
document.getElementById('bambuStatusMessage').innerText = 'Error while removing: ' + error.message;
});
}
function checkSpoolmanInstance() {
const url = document.getElementById('spoolmanUrl').value;
const spoolmanOctoEnabled = document.getElementById('spoolmanOctoEnabled').checked;
@@ -114,12 +89,7 @@
.then(data => {
if (data.healthy) {
document.getElementById('bambuStatusMessage').innerText = 'Bambu Credentials saved!';
// Reload with forced cache refresh after short delay
setTimeout(() => {
window.location.reload(true);
window.location.href = '/';
}, 1500);
} else {
} else {
document.getElementById('bambuStatusMessage').innerText = 'Error while saving Bambu Credentials.';
}
})
@@ -192,8 +162,7 @@
</div>
<button style="margin: 0;" onclick="saveBambuCredentials()">Save Bambu Credentials</button>
<button style="margin: 0; background-color: red;" onclick="removeBambuCredentials()">Remove Credentials</button>
<p id="bambuStatusMessage"></p>
<p id="bambuStatusMessage"></p>
</div>
</div>
</div>
+12 -7
View File
@@ -147,13 +147,6 @@ function updateFilamentDropdown(selectedSmId = null) {
if (vendorId) {
const filteredFilaments = spoolsData.filter(spool => {
if (!spool?.filament?.vendor?.id) {
console.log('Problem aufgetreten bei: ', spool?.filament?.vendor);
console.log('Problematische Spulen:',
spoolsData.filter(spool => !spool?.filament?.vendor?.id));
return false;
}
const hasValidNfcId = spool.extra &&
spool.extra.nfc_id &&
spool.extra.nfc_id !== '""' &&
@@ -247,6 +240,18 @@ async function fetchSpoolData() {
}
}
/*
// Exportiere Funktionen
window.getSpoolData = () => spoolsData;
window.reloadSpoolData = initSpoolman;
window.populateVendorDropdown = populateVendorDropdown;
window.updateFilamentDropdown = updateFilamentDropdown;
window.toggleFilamentDropdown = () => {
const content = document.getElementById("filament-dropdown-content");
content.classList.toggle("show");
};
*/
// Event Listener
document.addEventListener('DOMContentLoaded', () => {
initSpoolman();
-2
View File
@@ -129,7 +129,6 @@
if (data.status === 'success' || lastReceivedProgress >= 98) {
clearTimeout(wsReconnectTimer);
setTimeout(() => {
window.location.reload(true);
window.location.href = '/';
}, 30000);
}
@@ -165,7 +164,6 @@
status.className = 'status success';
status.style.display = 'block';
setTimeout(() => {
window.location.reload(true);
window.location.href = '/';
}, 30000);
}
-10
View File
@@ -55,8 +55,6 @@
<h5 class="card-title">Sacle Calibration</h5>
<button id="calibrateBtn" class="btn btn-primary">Calibrate Scale</button>
<button id="tareBtn" class="btn btn-secondary">Tare Scale</button>
&nbsp;&nbsp;&nbsp;Enable Auto-TARE <input type="checkbox" id="autoTareCheckbox" onchange="setAutoTare(this.checked);"
{{autoTare}}>
<div id="statusMessage" class="mt-3"></div>
</div>
</div>
@@ -141,14 +139,6 @@
payload: 'tare'
}));
});
// Add auto-tare function
function setAutoTare(enabled) {
ws.send(JSON.stringify({
type: 'scale',
payload: 'setAutoTare',
enabled: enabled
}));
}
// WebSocket-Verbindung beim Laden der Seite initiieren
connectWebSocket();
+2 -2
View File
@@ -9,8 +9,8 @@
; https://docs.platformio.org/page/projectconf.html
[common]
version = "0.2.1"
to_old_version = "0.2.0"
version = "1.4.1"
to_old_version = "1.4.0"
##
[env:esp32dev]
+1 -1
View File
@@ -14,7 +14,7 @@ def copy_file(input_file, output_file):
def should_compress(file):
# Skip compression for spoolman.html
if file == 'spoolman.html' or file == 'waage.html':
if file == 'spoolman.html':
return False
# Komprimiere nur bestimmte Dateitypen
return file.endswith(('.js', '.png', '.css', '.html'))
+5 -16
View File
@@ -3,7 +3,7 @@
#include <ArduinoJson.h>
#include "commonFS.h"
volatile spoolmanApiStateType spoolmanApiState = API_INIT;
bool spoolman_connected = false;
String spoolmanUrl = "";
bool octoEnabled = false;
String octoUrl = "";
@@ -85,8 +85,7 @@ JsonDocument fetchSingleSpoolInfo(int spoolId) {
}
void sendToApi(void *parameter) {
spoolmanApiState = API_TRANSMITTING;
SendToApiParams *params = (SendToApiParams *)parameter;
SendToApiParams* params = (SendToApiParams*)parameter;
// Extrahiere die Werte
String httpType = params->httpType;
@@ -95,17 +94,13 @@ void sendToApi(void *parameter) {
String octoToken = params->octoToken;
HTTPClient http;
http.setReuse(false);
http.begin(spoolsUrl);
http.addHeader("Content-Type", "application/json");
if (octoEnabled && octoToken != "") http.addHeader("X-Api-Key", octoToken);
int httpCode;
int httpCode = http.PUT(updatePayload);
if (httpType == "PATCH") httpCode = http.PATCH(updatePayload);
else if (httpType == "POST")
httpCode = http.POST(updatePayload);
else
httpCode = http.PUT(updatePayload);
if (httpType == "POST") httpCode = http.POST(updatePayload);
if (httpCode == HTTP_CODE_OK) {
Serial.println("Spoolman erfolgreich aktualisiert");
@@ -116,12 +111,10 @@ void sendToApi(void *parameter) {
}
http.end();
vTaskDelay(50 / portTICK_PERIOD_MS);
// Speicher freigeben
delete params;
vTaskDelete(NULL);
spoolmanApiState = API_IDLE;
}
bool updateSpoolTagId(String uidString, const char* payload) {
@@ -171,7 +164,6 @@ bool updateSpoolTagId(String uidString, const char* payload) {
0, // Priorität
NULL // Task-Handle (nicht benötigt)
);
updateDoc.clear();
return true;
}
@@ -208,7 +200,6 @@ uint8_t updateSpoolWeight(String spoolId, uint16_t weight) {
0, // Priorität
NULL // Task-Handle (nicht benötigt)
);
updateDoc.clear();
return 1;
}
@@ -246,7 +237,6 @@ bool updateSpoolOcto(int spoolId) {
0, // Priorität
NULL // Task-Handle (nicht benötigt)
);
updateDoc.clear();
return true;
}
@@ -479,8 +469,7 @@ bool checkSpoolmanInstance(const String& url) {
return false;
}
spoolmanApiState = API_IDLE;
oledShowTopRow();
spoolman_connected = true;
return strcmp(status, "healthy") == 0;
}
}
-7
View File
@@ -6,14 +6,7 @@
#include "website.h"
#include "display.h"
#include <ArduinoJson.h>
typedef enum
{
API_INIT,
API_IDLE,
API_TRANSMITTING
} spoolmanApiStateType;
extern volatile spoolmanApiStateType spoolmanApiState;
extern bool spoolman_connected;
extern String spoolmanUrl;
extern bool octoEnabled;
+10 -42
View File
@@ -27,7 +27,6 @@ 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;
@@ -38,35 +37,6 @@ int ams_count = 0;
String amsJsonData; // Speichert das fertige JSON für WebSocket-Clients
AMSData ams_data[MAX_AMS]; // Definition des Arrays;
bool removeBambuCredentials()
{
if (BambuMqttTask)
{
vTaskDelete(BambuMqttTask);
}
if (!removeJsonValue("/bambu_credentials.json"))
{
Serial.println("Fehler beim Löschen der Bambu-Credentials.");
return false;
}
// Löschen der globalen Variablen
g_bambu_ip = "";
g_bambu_accesscode = "";
g_bambu_serialnr = "";
bambu_ip = nullptr;
bambu_accesscode = nullptr;
bambu_serialnr = nullptr;
autoSendToBambu = false;
autoSetToBambuSpoolId = 0;
ams_count = 0;
amsJsonData = "";
bambuDisabled = true;
return true;
}
bool saveBambuCredentials(const String& ip, const String& serialnr, const String& accesscode, bool autoSend, const String& autoSendTime) {
if (BambuMqttTask) {
vTaskDelete(BambuMqttTask);
@@ -296,10 +266,8 @@ bool setBambuSpool(String payload) {
JsonDocument doc;
DeserializationError error = deserializeJson(doc, payload);
if (error) {
Serial.print("Error parsing setBambuSpool-JSON: ");
Serial.print("Error parsing JSON: ");
Serial.println(error.c_str());
Serial.print("Free Heap-Memory: ");
Serial.println(ESP.getFreeHeap());
return false;
}
@@ -507,9 +475,7 @@ void mqtt_callback(char* topic, byte* payload, unsigned int length) {
message = "";
if (error)
{
Serial.print("Free Heap-Memory: ");
Serial.println(ESP.getFreeHeap());
Serial.print("Error parsing MQTT-JSON: ");
Serial.print("Fehler beim Parsen des JSON: ");
Serial.println(error.c_str());
return;
}
@@ -716,12 +682,10 @@ void mqtt_loop(void * parameter) {
}
// Periodically check connection status
if (now - lastCheck > 60000) { // Check every 60 seconds
if (now - lastCheck > 30000) { // Check every 30 seconds
Serial.print("MQTT Status Check - Connected: ");
Serial.println(client.connected() ? "Yes" : "No");
lastCheck = now;
Serial.print("Free Heap-Memory: ");
Serial.println(ESP.getFreeHeap());
}
client.loop();
@@ -736,13 +700,14 @@ bool setupMqtt() {
bool success = loadBambuCredentials();
if (!success) {
bambuDisabled = true;
Serial.println("Failed to load Bambu credentials");
oledShowMessage("Bambu Credentials Missing");
vTaskDelay(2000 / portTICK_PERIOD_MS);
return false;
}
if (success && bambu_ip != "" && bambu_accesscode != "" && bambu_serialnr != "")
{
bambuDisabled = false;
sslClient.setCACert(root_ca);
sslClient.setInsecure();
client.setServer(bambu_ip, 8883);
@@ -799,7 +764,10 @@ bool setupMqtt() {
}
else
{
bambuDisabled = true;
Serial.println("Fehler: Keine MQTT-Daten vorhanden");
oledShowMessage("Bambu Credentials Missing");
oledShowTopRow();
vTaskDelay(2000 / portTICK_PERIOD_MS);
return false;
}
return true;
-2
View File
@@ -30,9 +30,7 @@ extern int ams_count;
extern AMSData ams_data[MAX_AMS];
extern bool autoSendToBambu;
extern int autoSetToBambuSpoolId;
extern bool bambuDisabled;
bool removeBambuCredentials();
bool loadBambuCredentials();
bool saveBambuCredentials(const String& bambu_ip, const String& bambu_serialnr, const String& bambu_accesscode, const bool autoSend, const String& autoSendTime);
bool setupMqtt();
-17
View File
@@ -1,23 +1,6 @@
#include "commonFS.h"
#include <LittleFS.h>
bool removeJsonValue(const char *filename)
{
File file = LittleFS.open(filename, "r");
if (!file)
{
return true;
}
file.close();
if (!LittleFS.remove(filename))
{
Serial.print("Fehler beim Löschen der Datei: ");
Serial.println(filename);
return false;
}
return true;
}
bool saveJsonValue(const char* filename, const JsonDocument& doc) {
File file = LittleFS.open(filename, "w");
if (!file) {
+1 -2
View File
@@ -5,8 +5,7 @@
#include <ArduinoJson.h>
#include <LittleFS.h>
bool removeJsonValue(const char *filename);
bool saveJsonValue(const char *filename, const JsonDocument &doc);
bool saveJsonValue(const char* filename, const JsonDocument& doc);
bool loadJsonValue(const char* filename, JsonDocument& doc);
void initializeFileSystem();
-5
View File
@@ -19,11 +19,6 @@ const uint16_t SCALE_LEVEL_WEIGHT = 500;
uint16_t defaultScaleCalibrationValue = 430;
// ***** HX711
// ***** TTP223 (Touch Sensor)
// TTP223 circuit wiring
const uint8_t TTP223_PIN = 25;
// ***** TTP223
// ***** Display
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// On an ESP32: 21(SDA), 22(SCL)
-1
View File
@@ -10,7 +10,6 @@ extern const uint8_t LOADCELL_DOUT_PIN;
extern const uint8_t LOADCELL_SCK_PIN;
extern const uint8_t calVal_eepromAdress;
extern const uint16_t SCALE_LEVEL_WEIGHT;
extern const uint8_t TTP223_PIN;
extern const int8_t OLED_RESET;
extern const uint8_t SCREEN_ADDRESS;
+3 -6
View File
@@ -177,12 +177,9 @@ void oledShowTopRow() {
display.drawBitmap(50, 0, bitmap_off , 16, 16, WHITE);
}
if (spoolmanApiState != API_INIT)
{
display.drawBitmap(80, 0, bitmap_spoolman_on, 16, 16, WHITE);
}
else
{
if (spoolman_connected == 1) {
display.drawBitmap(80, 0, bitmap_spoolman_on , 16, 16, WHITE);
} else {
display.drawBitmap(80, 0, bitmap_off , 16, 16, WHITE);
}
+21 -40
View File
@@ -15,7 +15,6 @@
bool mainTaskWasPaused = 0;
uint8_t scaleTareCounter = 0;
bool touchSensorConnected = false;
// ##### SETUP #####
void setup() {
@@ -40,6 +39,7 @@ void setup() {
setupWebserver(server);
// Spoolman API
// api.cpp
initSpoolman();
// Bambu MQTT
@@ -48,16 +48,7 @@ void setup() {
// NFC Reader
startNfc();
// Touch Sensor
pinMode(TTP223_PIN, INPUT_PULLUP);
if (digitalRead(TTP223_PIN) == LOW)
{
Serial.println("Touch Sensor is connected");
touchSensorConnected = true;
}
// Scale
start_scale(touchSensorConnected);
start_scale();
// WDT initialisieren mit 10 Sekunden Timeout
bool panic = true; // Wenn true, löst ein WDT-Timeout einen System-Panik aus
@@ -93,25 +84,13 @@ uint8_t autoAmsCounter = 0;
uint8_t weightSend = 0;
int16_t lastWeight = 0;
// WIFI check variables
unsigned long lastWifiCheckTime = 0;
const unsigned long wifiCheckInterval = 60000; // Überprüfe alle 60 Sekunden (60000 ms)
// Button debounce variables
unsigned long lastButtonPress = 0;
const unsigned long debounceDelay = 500; // 500 ms debounce delay
// ##### PROGRAM START #####
void loop() {
unsigned long currentMillis = millis();
// Überprüfe den Status des Touch Sensors
if (touchSensorConnected && digitalRead(TTP223_PIN) == HIGH && currentMillis - lastButtonPress > debounceDelay)
{
lastButtonPress = currentMillis;
scaleTareRequest = true;
}
// Überprüfe regelmäßig die WLAN-Verbindung
if (intervalElapsed(currentMillis, lastWifiCheckTime, wifiCheckInterval)) {
checkWiFiConnection();
@@ -119,14 +98,9 @@ void loop() {
// Wenn Bambu auto set Spool aktiv
if (autoSendToBambu && autoSetToBambuSpoolId > 0) {
if (!bambuDisabled && !bambu_connected)
{
bambu_restart();
}
if (intervalElapsed(currentMillis, lastAutoSetBambuAmsTime, autoSetBambuAmsInterval))
{
if (nfcReaderState == NFC_IDLE)
if (hasReadRfidTag == 0)
{
lastAutoSetBambuAmsTime = currentMillis;
oledShowMessage("Auto Set " + String(autoSetBambuAmsCounter - autoAmsCounter) + "s");
@@ -160,7 +134,7 @@ void loop() {
// Ausgabe der Waage auf Display
if(pauseMainTask == 0)
{
if (mainTaskWasPaused || (weight != lastWeight && nfcReaderState == NFC_IDLE && (!autoSendToBambu || autoSetToBambuSpoolId == 0)))
if (mainTaskWasPaused || (weight != lastWeight && hasReadRfidTag == 0 && (!autoSendToBambu || autoSetToBambuSpoolId == 0)))
{
(weight < 2) ? ((weight < -2) ? oledShowMessage("!! -0") : oledShowWeight(0)) : oledShowWeight(weight);
}
@@ -173,18 +147,27 @@ void loop() {
// Wenn Timer abgelaufen und nicht gerade ein RFID-Tag geschrieben wird
if (currentMillis - lastWeightReadTime >= weightReadInterval && nfcReaderState < NFC_WRITING)
if (currentMillis - lastWeightReadTime >= weightReadInterval && hasReadRfidTag < 3)
{
lastWeightReadTime = currentMillis;
// Prüfen ob die Waage korrekt genullt ist
if (autoTare && (weight > 0 && weight < 5) || weight < 0)
if ((weight > 0 && weight < 5) || weight < 0)
{
scale_tare_counter++;
if(scaleTareCounter < 5)
{
scaleTareCounter++;
}
else
{
scaleTareRequest = true;
scaleTareCounter = 0;
}
}
else
{
scale_tare_counter = 0;
scaleTareCounter = 0;
}
// Prüfen ob das Gewicht gleich bleibt und dann senden
@@ -200,17 +183,15 @@ void loop() {
}
// reset weight counter after writing tag
// TBD: what exactly is the logic behind this?
if (currentMillis - lastWeightReadTime >= weightReadInterval && nfcReaderState != NFC_IDLE && nfcReaderState != NFC_READ_SUCCESS)
if (currentMillis - lastWeightReadTime >= weightReadInterval && hasReadRfidTag > 1)
{
weigthCouterToApi = 0;
}
lastWeight = weight;
// Wenn ein Tag mit SM id erkannte wurde und der Waage Counter anspricht an SM Senden
if (spoolId != "" && weigthCouterToApi > 3 && weightSend == 0 && nfcReaderState == NFC_READ_SUCCESS)
{
if (spoolId != "" && weigthCouterToApi > 3 && weightSend == 0 && hasReadRfidTag == 1) {
oledShowIcon("loading");
if (updateSpoolWeight(spoolId, weight))
{
@@ -230,6 +211,6 @@ void loop() {
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
}
esp_task_wdt_reset();
}
+120 -294
View File
@@ -7,23 +7,9 @@
#include "api.h"
#include "esp_task_wdt.h"
#include "scale.h"
#include <SPI.h>
// Pin definitions for both PN532 chips
#define PN532_SCK (18) // SPI SCK
#define PN532_MISO (19) // SPI MISO
#define PN532_MOSI (23) // SPI MOSI
// CS pins for each PN532
#define PN532_CS1 (5) // CS for first PN532
#define PN532_CS2 (4) // CS for second PN532
// Mifare authentication key
uint8_t keyA[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
// Create two PN532 instances
Adafruit_PN532 nfc1(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_CS1);
Adafruit_PN532 nfc2(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_CS2);
//Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS);
Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);
TaskHandle_t RfidReaderTask;
@@ -32,7 +18,7 @@ String spoolId = "";
String nfcJsonData = "";
volatile bool pauseBambuMqttTask = false;
volatile nfcReaderStateType nfcReaderState = NFC_IDLE;
volatile uint8_t hasReadRfidTag = 0;
// 0 = nicht gelesen
// 1 = erfolgreich gelesen
// 2 = fehler beim Lesen
@@ -42,165 +28,6 @@ volatile nfcReaderStateType nfcReaderState = NFC_IDLE;
// 6 = reading
// ***** PN532
// Buffer for reading data
uint8_t data[32];
// Function to initialize a specific PN532
bool initPN532(Adafruit_PN532 &pn532) {
pn532.begin();
uint32_t versiondata = pn532.getFirmwareVersion();
if (!versiondata) {
Serial.println("Didn't find PN532 board");
return false;
}
// Got valid data, print it out!
Serial.print("Found chip PN5"); Serial.println((versiondata >> 24) & 0xFF, HEX);
Serial.print("Firmware ver. "); Serial.print((versiondata >> 16) & 0xFF, DEC);
Serial.print('.'); Serial.println((versiondata >> 8) & 0xFF, DEC);
// Configure board to read RFID tags
pn532.SAMConfig();
Serial.println("Waiting for an ISO14443A Card ...");
return true;
}
void initNfc() {
// Configure CS pins as outputs
pinMode(PN532_CS1, OUTPUT);
pinMode(PN532_CS2, OUTPUT);
digitalWrite(PN532_CS1, HIGH); // Deselect both chips initially
digitalWrite(PN532_CS2, HIGH);
// Initialize SPI
SPI.begin(PN532_SCK, PN532_MISO, PN532_MOSI);
SPI.setFrequency(1000000); // 1MHz SPI clock
// Initialize both PN532 chips
if (!initPN532(nfc1)) {
Serial.println("Failed to initialize PN532 #1");
return;
}
if (!initPN532(nfc2)) {
Serial.println("Failed to initialize PN532 #2");
return;
}
Serial.println("Both PN532 chips initialized successfully");
}
// Function to read a specific PN532
bool readPN532(Adafruit_PN532 &pn532, uint8_t *uid, uint8_t *uidLength) {
uint8_t success;
success = pn532.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, uidLength);
return success;
}
// Function to write to a specific PN532
bool writePN532(Adafruit_PN532 &pn532, uint8_t *uid, uint8_t uidLength, uint8_t *data, uint8_t dataLen) {
if (!pn532.mifareclassic_AuthenticateBlock(uid, uidLength, 4, 1, keyA)) {
Serial.println("Failed to authenticate block");
return false;
}
if (!pn532.mifareclassic_WriteDataBlock(4, data)) {
Serial.println("Failed to write block");
return false;
}
return true;
}
void loopNfc() {
uint8_t uid1[] = {0, 0, 0, 0, 0, 0, 0};
uint8_t uid2[] = {0, 0, 0, 0, 0, 0, 0};
uint8_t uidLength1 = 0;
uint8_t uidLength2 = 0;
// Try to read from both PN532 chips
bool success1 = readPN532(nfc1, uid1, &uidLength1);
bool success2 = readPN532(nfc2, uid2, &uidLength2);
if (success1 || success2) {
// Process the first tag if found
if (success1) {
processTag(uid1, uidLength1, 1);
}
// Process the second tag if found
if (success2) {
processTag(uid2, uidLength2, 2);
}
}
}
void processTag(uint8_t *uid, uint8_t uidLength, uint8_t readerNumber) {
Adafruit_PN532 &pn532 = (readerNumber == 1) ? nfc1 : nfc2;
Serial.print("Reader "); Serial.print(readerNumber); Serial.println(" found tag:");
Serial.print("UID Length: "); Serial.println(uidLength);
Serial.print("UID Value: ");
for (uint8_t i = 0; i < uidLength; i++) {
Serial.print(" 0x"); Serial.print(uid[i], HEX);
}
Serial.println("");
if (uidLength == 7) {
uint16_t tagSize = readTagSize(pn532);
if(tagSize > 0) {
Serial.print("Tag size: "); Serial.println(tagSize);
uint8_t* data = (uint8_t*)malloc(tagSize);
memset(data, 0, tagSize);
// Mehrere Leseversuche
bool readSuccess = false;
for(int attempt = 0; attempt < 3 && !readSuccess; attempt++) {
readSuccess = true;
uint8_t numPages = tagSize / 4;
for (uint8_t i = 4; i < 4 + numPages; i++) {
if (!pn532.ntag2xx_ReadPage(i, data + (i - 4) * 4)) {
Serial.print("Failed to read page "); Serial.println(i);
readSuccess = false;
break;
}
delay(5); // Kleine Pause zwischen den Seiten
}
if (!readSuccess) {
delay(50); // Pause vor erneutem Versuch
}
}
if (readSuccess) {
Serial.println("Successfully read tag data.");
processNfcData(data, createTagId(uid, uidLength));
} else {
Serial.println("Failed to read tag data after 3 attempts");
oledShowMessage("Read Error");
}
free(data);
}
}
}
void processNfcData(uint8_t *data, String tagId) {
// Process the data and send it via WebSocket
if (decodeNdefAndReturnJson(data)) {
nfcReaderState = NFC_READ_SUCCESS;
sendNfcData(nullptr);
} else {
nfcReaderState = NFC_READ_ERROR;
oledShowMessage("NFC-Tag unknown");
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
}
// Function to write to a specific tag
bool writeNfcTag(uint8_t *uid, uint8_t uidLength, uint8_t *data, uint8_t dataLen, uint8_t readerNumber) {
// Select the appropriate PN532 based on reader number
Adafruit_PN532 &pn532 = (readerNumber == 1) ? nfc1 : nfc2;
return writePN532(pn532, uid, uidLength, data, dataLen);
}
// ##### Funktionen für RFID #####
void payloadToJson(uint8_t *data) {
@@ -253,7 +80,7 @@ bool formatNdefTag() {
// Schreibe die Initialisierungsnachricht auf die ersten Seiten
for (int i = 0; i < sizeof(ndefInit); i += 4) {
if (!nfc1.ntag2xx_WritePage(pageOffset + (i / 4), &ndefInit[i])) {
if (!nfc.ntag2xx_WritePage(pageOffset + (i / 4), &ndefInit[i])) {
success = false;
break;
}
@@ -262,15 +89,16 @@ bool formatNdefTag() {
return success;
}
uint16_t readTagSize(Adafruit_PN532 &pn532) {
uint8_t buffer[4];
memset(buffer, 0, 4);
pn532.ntag2xx_ReadPage(3, buffer);
return buffer[2] * 8;
uint16_t readTagSize()
{
uint8_t buffer[4];
memset(buffer, 0, 4);
nfc.ntag2xx_ReadPage(3, buffer);
return buffer[2]*8;
}
uint8_t ntag2xx_WriteNDEF(const char *payload, Adafruit_PN532 &pn532) {
uint16_t tagSize = readTagSize(pn532);
uint8_t ntag2xx_WriteNDEF(const char *payload) {
uint16_t tagSize = readTagSize();
Serial.print("Tag Size: ");Serial.println(tagSize);
uint8_t pageBuffer[4] = {0, 0, 0, 0};
@@ -329,7 +157,11 @@ uint8_t ntag2xx_WriteNDEF(const char *payload, Adafruit_PN532 &pn532) {
int bytesToWrite = (totalSize < 4) ? totalSize : 4;
memcpy(pageBuffer, combinedData + a, bytesToWrite);
if (!(pn532.ntag2xx_WritePage(4+i, pageBuffer)))
//uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
//uint8_t uidLength;
//nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 100);
if (!(nfc.ntag2xx_WritePage(4+i, pageBuffer)))
{
Serial.println("Fehler beim Schreiben der Seite.");
free(combinedData);
@@ -337,6 +169,8 @@ uint8_t ntag2xx_WriteNDEF(const char *payload, Adafruit_PN532 &pn532) {
}
yield();
//esp_task_wdt_reset();
i++;
a += 4;
totalSize -= bytesToWrite;
@@ -345,7 +179,7 @@ uint8_t ntag2xx_WriteNDEF(const char *payload, Adafruit_PN532 &pn532) {
// Ensure the NDEF message is properly terminated
memset(pageBuffer, 0, 4);
pageBuffer[0] = 0xFE; // NDEF record footer
if (!(pn532.ntag2xx_WritePage(4+i, pageBuffer)))
if (!(nfc.ntag2xx_WritePage(4+i, pageBuffer)))
{
Serial.println("Fehler beim Schreiben des End-Bits.");
free(combinedData);
@@ -404,43 +238,32 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage) {
void writeJsonToTag(void *parameter) {
const char* payload = (const char*)parameter;
// Gib die erstellte NDEF-Message aus
Serial.println("Erstelle NDEF-Message...");
Serial.println(payload);
nfcReaderState = NFC_WRITING;
hasReadRfidTag = 3;
vTaskSuspend(RfidReaderTask);
vTaskDelay(50 / portTICK_PERIOD_MS);
//pauseBambuMqttTask = true;
// aktualisieren der Website wenn sich der Status ändert
sendNfcData(nullptr);
vTaskDelay(100 / portTICK_PERIOD_MS);
oledShowMessage("Waiting for NFC-Tag");
// Try both readers
// Wait 10sec for tag
uint8_t success = 0;
String uidString = "";
Adafruit_PN532* activeReader = nullptr;
for (uint16_t i = 0; i < 20; i++) {
// Try first reader
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
uint8_t uidLength;
success = nfc1.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 250);
if (!success) {
// Try second reader
success = nfc2.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 250);
if (success) {
activeReader = &nfc2;
}
} else {
activeReader = &nfc1;
}
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 500);
if (success) {
for (uint8_t i = 0; i < uidLength; i++) {
uidString += String(uid[i], HEX);
if (i < uidLength - 1) {
uidString += ":";
uidString += ":"; // Optional: Trennzeichen hinzufügen
}
}
foundNfcTag(nullptr, success);
@@ -454,42 +277,50 @@ void writeJsonToTag(void *parameter) {
vTaskDelay(pdMS_TO_TICKS(1));
}
if (success && activeReader != nullptr) {
if (success)
{
oledShowIcon("transfer");
// Schreibe die NDEF-Message auf den Tag
success = ntag2xx_WriteNDEF(payload, *activeReader);
if (success) {
success = ntag2xx_WriteNDEF(payload);
if (success)
{
Serial.println("NDEF-Message erfolgreich auf den Tag geschrieben");
//oledShowMessage("NFC-Tag written");
oledShowIcon("success");
vTaskDelay(1000 / portTICK_PERIOD_MS);
nfcReaderState = NFC_WRITE_SUCCESS;
hasReadRfidTag = 5;
// aktualisieren der Website wenn sich der Status ändert
sendNfcData(nullptr);
pauseBambuMqttTask = false;
if (updateSpoolTagId(uidString, payload)) {
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
uint8_t uidLength;
oledShowIcon("success");
while (activeReader->readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 500)) {
while (nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 500)) {
yield();
}
}
vTaskResume(RfidReaderTask);
vTaskDelay(500 / portTICK_PERIOD_MS);
} else {
}
else
{
Serial.println("Fehler beim Schreiben der NDEF-Message auf den Tag");
oledShowIcon("failed");
vTaskDelay(2000 / portTICK_PERIOD_MS);
nfcReaderState = NFC_WRITE_ERROR;
hasReadRfidTag = 4;
}
} else {
}
else
{
Serial.println("Fehler: Kein Tag zu schreiben gefunden.");
oledShowMessage("No NFC-Tag found");
vTaskDelay(2000 / portTICK_PERIOD_MS);
nfcReaderState = NFC_IDLE;
hasReadRfidTag = 0;
}
sendWriteResult(nullptr, success);
sendNfcData(nullptr);
@@ -503,7 +334,7 @@ void startWriteJsonToTag(const char* payload) {
char* payloadCopy = strdup(payload);
// Task nicht mehrfach starten
if (nfcReaderState != NFC_WRITING) {
if (hasReadRfidTag != 3) {
// Erstelle die Task
xTaskCreate(
writeJsonToTag, // Task-Funktion
@@ -517,79 +348,69 @@ void startWriteJsonToTag(const char* payload) {
}
void scanRfidTask(void * parameter) {
Serial.println("RFID Task gestartet");
if (nfcReaderState != NFC_WRITING)
Serial.println("RFID Task gestartet");
for(;;) {
// Wenn geschrieben wird Schleife aussetzen
if (hasReadRfidTag != 3)
{
yield();
uint8_t success = 0;
uint8_t uid[] = {0, 0, 0, 0, 0, 0, 0};
uint8_t success;
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
uint8_t uidLength;
Adafruit_PN532 *activeReader = nullptr;
// Try first reader with increased timeout
success = nfc1.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 150);
if (success)
{
activeReader = &nfc1;
}
else
{
delay(50); // Small delay between readers
// Try second reader with increased timeout
success = nfc2.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 150);
if (success)
{
activeReader = &nfc2;
}
}
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 1000);
foundNfcTag(nullptr, success);
if (success && nfcReaderState != NFC_READ_SUCCESS && activeReader != nullptr)
if (success && hasReadRfidTag != 1)
{
// Display some basic information about the card
Serial.println("Found an ISO14443A card");
nfcReaderState = NFC_READING;
hasReadRfidTag = 6;
oledShowIcon("transfer");
vTaskDelay(500 / portTICK_PERIOD_MS);
if (uidLength == 7)
{
uint16_t tagSize = readTagSize(*activeReader);
if (tagSize > 0)
uint16_t tagSize = readTagSize();
if(tagSize > 0)
{
uint8_t *data = (uint8_t *)malloc(tagSize);
// Create a buffer depending on the size of the tag
uint8_t* data = (uint8_t*)malloc(tagSize);
memset(data, 0, tagSize);
// We probably have an NTAG2xx card (though it could be Ultralight as well)
Serial.println("Seems to be an NTAG2xx tag (7 byte UID)");
uint8_t numPages = readTagSize(*activeReader) / 4;
for (uint8_t i = 4; i < 4 + numPages; i++)
{
if (!activeReader->ntag2xx_ReadPage(i, data + (i - 4) * 4))
uint8_t numPages = readTagSize()/4;
for (uint8_t i = 4; i < 4+numPages; i++) {
if (!nfc.ntag2xx_ReadPage(i, data+(i-4) * 4))
{
break;
break; // Stop if reading fails
}
if (data[(i - 4) * 4] == 0xFE)
// Check for NDEF message end
if (data[(i - 4) * 4] == 0xFE)
{
break;
break; // End of NDEF message
}
yield();
esp_task_wdt_reset();
vTaskDelay(pdMS_TO_TICKS(5)); // Increased delay between page reads
vTaskDelay(pdMS_TO_TICKS(1));
}
if (!decodeNdefAndReturnJson(data))
if (!decodeNdefAndReturnJson(data))
{
oledShowMessage("NFC-Tag unknown");
vTaskDelay(2000 / portTICK_PERIOD_MS);
nfcReaderState = NFC_READ_ERROR;
hasReadRfidTag = 2;
}
else
else
{
nfcReaderState = NFC_READ_SUCCESS;
hasReadRfidTag = 1;
}
free(data);
@@ -597,7 +418,7 @@ void scanRfidTask(void * parameter) {
else
{
oledShowMessage("NFC-Tag read error");
nfcReaderState = NFC_READ_ERROR;
hasReadRfidTag = 2;
}
}
else
@@ -606,53 +427,58 @@ void scanRfidTask(void * parameter) {
}
}
if (!success && nfcReaderState != NFC_IDLE)
if (!success && hasReadRfidTag > 0)
{
nfcReaderState = NFC_IDLE;
hasReadRfidTag = 0;
//uidString = "";
nfcJsonData = "";
Serial.println("Tag entfernt");
if (!autoSendToBambu)
oledShowWeight(weight);
if (!autoSendToBambu) oledShowWeight(weight);
}
// aktualisieren der Website wenn sich der Status ändert
sendNfcData(nullptr);
delay(100); // Add small delay at end of loop
}
yield();
}
void startNfc() {
initNfc();
BaseType_t result = xTaskCreatePinnedToCore(
scanRfidTask, /* Function to implement the task */
"RfidReader", /* Name of the task */
5115, /* Stack size in words */
NULL, /* Task input parameter */
rfidTaskPrio, /* Priority of the task */
&RfidReaderTask, /* Task handle. */
rfidTaskCore); /* Core where the task should run */
if (result != pdPASS) {
Serial.println("Fehler beim Erstellen des RFID Tasks");
} else {
Serial.println("RFID Task erfolgreich erstellt");
yield();
}
}
String createTagId(uint8_t *uid, uint8_t uidLength)
{
String tagId = ""; // Initialisieren Sie einen leeren String
void startNfc() {
nfc.begin(); // Beginne Kommunikation mit RFID Leser
delay(1000);
unsigned long versiondata = nfc.getFirmwareVersion(); // Lese Versionsnummer der Firmware aus
if (! versiondata) { // Wenn keine Antwort kommt
Serial.println("Kann kein RFID Board finden !"); // Sende Text "Kann kein..." an seriellen Monitor
//delay(5000);
//ESP.restart();
oledShowMessage("No RFID Board found");
delay(2000);
}
else {
Serial.print("Chip PN5 gefunden"); Serial.println((versiondata >> 24) & 0xFF, HEX); // Sende Text und Versionsinfos an seriellen
Serial.print("Firmware ver. "); Serial.print((versiondata >> 16) & 0xFF, DEC); // Monitor, wenn Antwort vom Board kommt
Serial.print('.'); Serial.println((versiondata >> 8) & 0xFF, DEC); //
// Erstellen Sie die Tag-ID basierend auf dem UID
for (uint8_t i = 0; i < uidLength; i++)
{
tagId += String(uid[i], HEX); // Konvertieren Sie die UID in einen String
if (i < uidLength - 1)
{
tagId += ":"; // Fügen Sie einen Trennstrich hinzu, wenn es nicht das letzte Element ist
nfc.SAMConfig();
// Set the max number of retry attempts to read from a card
// This prevents us from waiting forever for a card, which is
// the default behaviour of the PN532.
//nfc.setPassiveActivationRetries(0x7F);
//nfc.setPassiveActivationRetries(0xFF);
BaseType_t result = xTaskCreatePinnedToCore(
scanRfidTask, /* Function to implement the task */
"RfidReader", /* Name of the task */
5115, /* Stack size in words */
NULL, /* Task input parameter */
rfidTaskPrio, /* Priority of the task */
&RfidReaderTask, /* Task handle. */
rfidTaskCore); /* Core where the task should run */
if (result != pdPASS) {
Serial.println("Fehler beim Erstellen des RFID Tasks");
} else {
Serial.println("RFID Task erfolgreich erstellt");
}
}
return tagId; // Geben Sie die erstellte Tag-ID zurück
Serial.println("tagID:" + tagId);
}
+5 -21
View File
@@ -1,32 +1,16 @@
#pragma once
#ifndef NFC_H
#define NFC_H
#include <Arduino.h>
#include <Adafruit_PN532.h>
typedef enum
{
NFC_IDLE,
NFC_READING,
NFC_READ_SUCCESS,
NFC_READ_ERROR,
NFC_WRITING,
NFC_WRITE_SUCCESS,
NFC_WRITE_ERROR
} nfcReaderStateType;
void startNfc();
void startWriteJsonToTag(const char* payload);
void writeJsonToTag(void *parameter);
void scanRfidTask(void * parameter);
void processTag(uint8_t *uid, uint8_t uidLength, uint8_t readerNumber);
void processNfcData(uint8_t *data, String tagId);
bool decodeNdefAndReturnJson(const byte* encodedMessage);
void startWriteJsonToTag(const char* payload);
extern TaskHandle_t RfidReaderTask;
extern String nfcJsonData;
extern String spoolId;
extern volatile nfcReaderStateType nfcReaderState;
extern volatile uint8_t hasReadRfidTag;
extern volatile bool pauseBambuMqttTask;
// Function declarations
uint16_t readTagSize(Adafruit_PN532 &pn532);
String createTagId(uint8_t *uid, uint8_t uidLength);
#endif
+4 -42
View File
@@ -14,7 +14,6 @@ TaskHandle_t ScaleTask;
int16_t weight = 0;
uint8_t weigthCouterToApi = 0;
uint8_t scale_tare_counter = 0;
bool scaleTareRequest = false;
uint8_t pauseMainTask = 0;
uint8_t scaleCalibrated = 1;
@@ -22,26 +21,9 @@ uint8_t scaleCalibrated = 1;
Preferences preferences;
const char* NVS_NAMESPACE = "scale";
const char* NVS_KEY_CALIBRATION = "cal_value";
const char *NVS_KEY_AUTOTARE = "auto_tare";
bool autoTare = true;
// ##### Funktionen für Waage #####
uint8_t setAutoTare(bool autoTareValue)
{
Serial.print("Set AutoTare to ");
Serial.println(autoTareValue);
autoTare = autoTareValue;
// Speichern mit NVS
preferences.begin(NVS_NAMESPACE, false); // false = readwrite
preferences.putBool(NVS_KEY_AUTOTARE, autoTare);
preferences.end();
return 1;
}
uint8_t tareScale()
{
uint8_t tareScale() {
Serial.println("Tare scale");
scale.tare();
@@ -56,23 +38,11 @@ void scale_loop(void * parameter) {
for(;;) {
if (scale.is_ready())
{
// Waage automatisch Taren, wenn zu lange Abweichung
if (autoTare && scale_tare_counter >= 5)
{
Serial.println("Auto Tare scale");
scale.tare();
scale_tare_counter = 0;
}
// Waage manuell Taren
if (scaleTareRequest == true)
// Waage nochmal Taren, wenn zu lange Abweichung
if (scaleTareRequest == true)
{
Serial.println("Re-Tare scale");
oledShowMessage("TARE Scale");
vTaskDelay(pdMS_TO_TICKS(1000));
scale.tare();
vTaskDelay(pdMS_TO_TICKS(1000));
oledShowWeight(0);
scaleTareRequest = false;
}
@@ -83,21 +53,13 @@ void scale_loop(void * parameter) {
}
}
void start_scale(bool touchSensorConnected)
{
void start_scale() {
Serial.println("Prüfe Calibration Value");
float calibrationValue;
// NVS lesen
preferences.begin(NVS_NAMESPACE, true); // true = readonly
calibrationValue = preferences.getFloat(NVS_KEY_CALIBRATION, defaultScaleCalibrationValue);
// auto Tare
// Wenn Touch Sensor verbunden, dann autoTare auf false setzen
// Danach prüfen was in NVS gespeichert ist
autoTare = (touchSensorConnected) ? false : true;
autoTare = preferences.getBool(NVS_KEY_AUTOTARE, autoTare);
preferences.end();
Serial.print("Read Scale Calibration Value ");
+2 -4
View File
@@ -4,19 +4,17 @@
#include <Arduino.h>
#include "HX711.h"
uint8_t setAutoTare(bool autoTareValue);
uint8_t start_scale(bool touchSensorConnected);
uint8_t start_scale();
uint8_t calibrate_scale();
uint8_t tareScale();
extern HX711 scale;
extern int16_t weight;
extern uint8_t weigthCouterToApi;
extern uint8_t scale_tare_counter;
extern uint8_t scaleTareRequest;
extern uint8_t pauseMainTask;
extern uint8_t scaleCalibrated;
extern bool autoTare;
extern TaskHandle_t ScaleTask;
+37 -66
View File
@@ -22,13 +22,14 @@ AsyncWebServer server(webserverPort);
AsyncWebSocket ws("/ws");
uint8_t lastSuccess = 0;
nfcReaderStateType lastnfcReaderState = NFC_IDLE;
uint8_t lastHasReadRfidTag = 0;
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
if (type == WS_EVT_CONNECT) {
Serial.println("Neuer Client verbunden!");
// Sende die AMS-Daten an den neuen Client
if (!bambuDisabled) sendAmsData(client);
sendAmsData(client);
sendNfcData(client);
foundNfcTag(client, 0);
sendWriteResult(client, 3);
@@ -42,7 +43,6 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
String message = String((char*)data);
JsonDocument doc;
deserializeJson(doc, message);
bool spoolmanConnected = (spoolmanApiState != API_INIT);
if (doc["type"] == "heartbeat") {
// Sende Heartbeat-Antwort
@@ -50,7 +50,7 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
"\"type\":\"heartbeat\","
"\"freeHeap\":" + String(ESP.getFreeHeap()/1024) + ","
"\"bambu_connected\":" + String(bambu_connected) + ","
"\"spoolman_connected\":" + String(spoolmanConnected) + ""
"\"spoolman_connected\":" + String(spoolman_connected) + ""
"}");
}
@@ -73,11 +73,6 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
success = calibrate_scale();
}
if (doc["payload"] == "setAutoTare")
{
success = setAutoTare(doc["enabled"].as<bool>());
}
if (success) {
ws.textAll("{\"type\":\"scale\",\"payload\":\"success\"}");
} else {
@@ -144,33 +139,34 @@ void foundNfcTag(AsyncWebSocketClient *client, uint8_t success) {
}
void sendNfcData(AsyncWebSocketClient *client) {
if (lastnfcReaderState == nfcReaderState)
return;
// TBD: Why is there no status for reading the tag?
switch (nfcReaderState)
{
case NFC_IDLE:
if (lastHasReadRfidTag == hasReadRfidTag) return;
if (hasReadRfidTag == 0) {
ws.textAll("{\"type\":\"nfcData\", \"payload\":{}}");
break;
case NFC_READ_SUCCESS:
}
else if (hasReadRfidTag == 1) {
ws.textAll("{\"type\":\"nfcData\", \"payload\":" + nfcJsonData + "}");
break;
case NFC_READ_ERROR:
}
else if (hasReadRfidTag == 2)
{
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Empty Tag or Data not readable\"}}");
break;
case NFC_WRITING:
}
else if (hasReadRfidTag == 3)
{
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Schreibe Tag...\"}}");
break;
case NFC_WRITE_SUCCESS:
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Tag erfolgreich geschrieben\"}}");
break;
case NFC_WRITE_ERROR:
}
else if (hasReadRfidTag == 4)
{
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Error writing to Tag\"}}");
break;
case DEFAULT:
}
else if (hasReadRfidTag == 5)
{
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Tag erfolgreich geschrieben\"}}");
}
else
{
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Something went wrong\"}}");
}
lastnfcReaderState = nfcReaderState;
}
lastHasReadRfidTag = hasReadRfidTag;
}
void sendAmsData(AsyncWebSocketClient *client) {
@@ -206,24 +202,18 @@ void setupWebserver(AsyncWebServer &server) {
});
// Route für Waage
server.on("/waage", HTTP_GET, [](AsyncWebServerRequest *request)
{
server.on("/waage", HTTP_GET, [](AsyncWebServerRequest *request){
Serial.println("Anfrage für /waage erhalten");
//AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/waage.html.gz", "text/html");
//response->addHeader("Content-Encoding", "gzip");
//response->addHeader("Cache-Control", CACHE_CONTROL);
String html = loadHtmlWithHeader("/waage.html");
html.replace("{{autoTare}}", (autoTare) ? "checked" : "");
request->send(200, "text/html", html); });
AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/waage.html.gz", "text/html");
response->addHeader("Content-Encoding", "gzip");
response->addHeader("Cache-Control", CACHE_CONTROL);
request->send(response);
});
// Route für RFID
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
Serial.println("Anfrage für /rfid erhalten");
String page = (bambuDisabled) ? "/rfid.html.gz" : "/rfid_bambu.html.gz";
AsyncWebServerResponse *response = request->beginResponse(LittleFS, page, "text/html");
AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/rfid.html.gz", "text/html");
response->addHeader("Content-Encoding", "gzip");
response->addHeader("Cache-Control", CACHE_CONTROL);
request->send(response);
@@ -296,16 +286,6 @@ void setupWebserver(AsyncWebServer &server) {
}
String url = request->getParam("url")->value();
if (url.indexOf("http://") == -1 && url.indexOf("https://") == -1)
{
url = "http://" + url;
}
// Remove trailing slash if exists
if (url.length() > 0 && url.charAt(url.length() - 1) == '/')
{
url = url.substring(0, url.length() - 1);
}
bool octoEnabled = (request->getParam("octoEnabled")->value() == "true") ? true : false;
String octoUrl = request->getParam("octoUrl")->value();
String octoToken = (request->getParam("octoToken")->value() != "") ? request->getParam("octoToken")->value() : "";
@@ -320,18 +300,8 @@ void setupWebserver(AsyncWebServer &server) {
request->send(200, "application/json", jsonResponse);
});
// Route für das Überprüfen der Bambu-Instanz
server.on("/api/bambu", HTTP_GET, [](AsyncWebServerRequest *request)
{
if (request->hasParam("remove")) {
if (removeBambuCredentials()) {
request->send(200, "application/json", "{\"success\": true}");
} else {
request->send(500, "application/json", "{\"success\": false, \"error\": \"Fehler beim Löschen der Bambu-Credentials\"}");
}
return;
}
// Route für das Überprüfen der Spoolman-Instanz
server.on("/api/bambu", HTTP_GET, [](AsyncWebServerRequest *request){
if (!request->hasParam("bambu_ip") || !request->hasParam("bambu_serialnr") || !request->hasParam("bambu_accesscode")) {
request->send(400, "application/json", "{\"success\": false, \"error\": \"Missing parameter\"}");
return;
@@ -355,7 +325,8 @@ void setupWebserver(AsyncWebServer &server) {
bool success = saveBambuCredentials(bambu_ip, bambu_serialnr, bambu_accesscode, autoSend, autoSendTime);
request->send(200, "application/json", "{\"healthy\": " + String(success ? "true" : "false") + "}"); });
request->send(200, "application/json", "{\"healthy\": " + String(success ? "true" : "false") + "}");
});
// Route für das Überprüfen der Spoolman-Instanz
server.on("/reboot", HTTP_GET, [](AsyncWebServerRequest *request){
+1 -1
View File
@@ -59,7 +59,7 @@ void initWiFi() {
if(wm_nonblocking) wm.setConfigPortalBlocking(false);
//wm.setConfigPortalTimeout(320); // Portal nach 5min schließen
wm.setWiFiAutoReconnect(true);
wm.setConnectTimeout(10);
wm.setConnectTimeout(5);
oledShowTopRow();
oledShowMessage("WiFi Setup");