Compare commits
21 Commits
8ff4e81826
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 4dee298b73 | |||
| c430c989ef | |||
| b40a2166f2 | |||
| 3590187cbe | |||
| 0302725bc7 | |||
| 75fbd5ebc3 | |||
| 53894a3746 | |||
| 360c925cfc | |||
| fc5d77c97b | |||
| f869bcc0c1 | |||
| b75be0ac06 | |||
| 1c01bfb2da | |||
| 15d0bfd8e9 | |||
| d363a7b905 | |||
| 9d7accc746 | |||
| c2e3dc1d46 | |||
| d81cf5d4e4 | |||
| 75e13387c8 | |||
| 6534419381 | |||
| e55b2d7fdf | |||
| 4aa81c7842 |
@@ -0,0 +1,3 @@
|
|||||||
|
.pio
|
||||||
|
.vscode
|
||||||
|
data
|
||||||
@@ -141,15 +141,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
+55
-56
@@ -11,7 +11,7 @@ let reconnectTimer = null;
|
|||||||
// WebSocket Funktionen
|
// WebSocket Funktionen
|
||||||
function startHeartbeat() {
|
function startHeartbeat() {
|
||||||
if (heartbeatTimer) clearInterval(heartbeatTimer);
|
if (heartbeatTimer) clearInterval(heartbeatTimer);
|
||||||
|
|
||||||
heartbeatTimer = setInterval(() => {
|
heartbeatTimer = setInterval(() => {
|
||||||
// Prüfe ob zu lange keine Antwort kam
|
// Prüfe ob zu lange keine Antwort kam
|
||||||
if (Date.now() - lastHeartbeatResponse > HEARTBEAT_TIMEOUT) {
|
if (Date.now() - lastHeartbeatResponse > HEARTBEAT_TIMEOUT) {
|
||||||
@@ -29,7 +29,7 @@ function startHeartbeat() {
|
|||||||
updateConnectionStatus();
|
updateConnectionStatus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Sende Heartbeat
|
// Sende Heartbeat
|
||||||
socket.send(JSON.stringify({ type: 'heartbeat' }));
|
socket.send(JSON.stringify({ type: 'heartbeat' }));
|
||||||
@@ -59,18 +59,18 @@ function initWebSocket() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
socket = new WebSocket('ws://' + window.location.host + '/ws');
|
socket = new WebSocket('ws://' + window.location.host + '/ws');
|
||||||
|
|
||||||
socket.onopen = function() {
|
socket.onopen = function () {
|
||||||
isConnected = true;
|
isConnected = true;
|
||||||
updateConnectionStatus();
|
updateConnectionStatus();
|
||||||
startHeartbeat(); // Starte Heartbeat nach erfolgreicher Verbindung
|
startHeartbeat(); // Starte Heartbeat nach erfolgreicher Verbindung
|
||||||
};
|
};
|
||||||
|
|
||||||
socket.onclose = function() {
|
socket.onclose = function () {
|
||||||
isConnected = false;
|
isConnected = false;
|
||||||
updateConnectionStatus();
|
updateConnectionStatus();
|
||||||
if (heartbeatTimer) clearInterval(heartbeatTimer);
|
if (heartbeatTimer) clearInterval(heartbeatTimer);
|
||||||
|
|
||||||
// Nur neue Verbindung versuchen, wenn kein Timer läuft
|
// Nur neue Verbindung versuchen, wenn kein Timer läuft
|
||||||
if (!reconnectTimer) {
|
if (!reconnectTimer) {
|
||||||
reconnectTimer = setTimeout(() => {
|
reconnectTimer = setTimeout(() => {
|
||||||
@@ -78,22 +78,22 @@ function initWebSocket() {
|
|||||||
}, RECONNECT_INTERVAL);
|
}, RECONNECT_INTERVAL);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
socket.onerror = function(error) {
|
socket.onerror = function (error) {
|
||||||
isConnected = false;
|
isConnected = false;
|
||||||
updateConnectionStatus();
|
updateConnectionStatus();
|
||||||
if (heartbeatTimer) clearInterval(heartbeatTimer);
|
if (heartbeatTimer) clearInterval(heartbeatTimer);
|
||||||
|
|
||||||
// Bei Fehler Verbindung schließen und neu aufbauen
|
// Bei Fehler Verbindung schließen und neu aufbauen
|
||||||
if (socket) {
|
if (socket) {
|
||||||
socket.close();
|
socket.close();
|
||||||
socket = null;
|
socket = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
socket.onmessage = function(event) {
|
socket.onmessage = function (event) {
|
||||||
lastHeartbeatResponse = Date.now(); // Aktualisiere Zeitstempel bei jeder Server-Antwort
|
lastHeartbeatResponse = Date.now(); // Aktualisiere Zeitstempel bei jeder Server-Antwort
|
||||||
|
|
||||||
const data = JSON.parse(event.data);
|
const data = JSON.parse(event.data);
|
||||||
if (data.type === 'amsData') {
|
if (data.type === 'amsData') {
|
||||||
displayAmsData(data.payload);
|
displayAmsData(data.payload);
|
||||||
@@ -109,13 +109,13 @@ function initWebSocket() {
|
|||||||
const bambuDot = document.getElementById('bambuDot');
|
const bambuDot = document.getElementById('bambuDot');
|
||||||
const spoolmanDot = document.getElementById('spoolmanDot');
|
const spoolmanDot = document.getElementById('spoolmanDot');
|
||||||
const ramStatus = document.getElementById('ramStatus');
|
const ramStatus = document.getElementById('ramStatus');
|
||||||
|
|
||||||
if (bambuDot) {
|
if (bambuDot) {
|
||||||
bambuDot.className = 'status-dot ' + (data.bambu_connected ? 'online' : 'offline');
|
bambuDot.className = 'status-dot ' + (data.bambu_connected ? 'online' : 'offline');
|
||||||
// Add click handler only when offline
|
// Add click handler only when offline
|
||||||
if (!data.bambu_connected) {
|
if (!data.bambu_connected) {
|
||||||
bambuDot.style.cursor = 'pointer';
|
bambuDot.style.cursor = 'pointer';
|
||||||
bambuDot.onclick = function() {
|
bambuDot.onclick = function () {
|
||||||
if (socket && socket.readyState === WebSocket.OPEN) {
|
if (socket && socket.readyState === WebSocket.OPEN) {
|
||||||
socket.send(JSON.stringify({
|
socket.send(JSON.stringify({
|
||||||
type: 'reconnect',
|
type: 'reconnect',
|
||||||
@@ -133,7 +133,7 @@ function initWebSocket() {
|
|||||||
// Add click handler only when offline
|
// Add click handler only when offline
|
||||||
if (!data.spoolman_connected) {
|
if (!data.spoolman_connected) {
|
||||||
spoolmanDot.style.cursor = 'pointer';
|
spoolmanDot.style.cursor = 'pointer';
|
||||||
spoolmanDot.onclick = function() {
|
spoolmanDot.onclick = function () {
|
||||||
if (socket && socket.readyState === WebSocket.OPEN) {
|
if (socket && socket.readyState === WebSocket.OPEN) {
|
||||||
socket.send(JSON.stringify({
|
socket.send(JSON.stringify({
|
||||||
type: 'reconnect',
|
type: 'reconnect',
|
||||||
@@ -161,7 +161,7 @@ function initWebSocket() {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
isConnected = false;
|
isConnected = false;
|
||||||
updateConnectionStatus();
|
updateConnectionStatus();
|
||||||
|
|
||||||
// Nur neue Verbindung versuchen, wenn kein Timer läuft
|
// Nur neue Verbindung versuchen, wenn kein Timer läuft
|
||||||
if (!reconnectTimer) {
|
if (!reconnectTimer) {
|
||||||
reconnectTimer = setTimeout(() => {
|
reconnectTimer = setTimeout(() => {
|
||||||
@@ -189,26 +189,26 @@ function updateConnectionStatus() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Event Listeners
|
// Event Listeners
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
initWebSocket();
|
initWebSocket();
|
||||||
|
|
||||||
// Event Listener für Checkbox
|
// Event Listener für Checkbox
|
||||||
document.getElementById("onlyWithoutSmId").addEventListener("change", function() {
|
document.getElementById("onlyWithoutSmId").addEventListener("change", function () {
|
||||||
const spoolsData = window.getSpoolData();
|
const spoolsData = window.getSpoolData();
|
||||||
window.populateVendorDropdown(spoolsData);
|
window.populateVendorDropdown(spoolsData);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Event Listener für Spoolman Events
|
// Event Listener für Spoolman Events
|
||||||
document.addEventListener('spoolDataLoaded', function(event) {
|
document.addEventListener('spoolDataLoaded', function (event) {
|
||||||
window.populateVendorDropdown(event.detail);
|
window.populateVendorDropdown(event.detail);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener('spoolmanError', function(event) {
|
document.addEventListener('spoolmanError', function (event) {
|
||||||
showNotification(`Spoolman Error: ${event.detail.message}`, false);
|
showNotification(`Spoolman Error: ${event.detail.message}`, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener('filamentSelected', function(event) {
|
document.addEventListener('filamentSelected', function (event) {
|
||||||
updateNfcInfo();
|
updateNfcInfo();
|
||||||
// Zeige Spool-Buttons wenn ein Filament ausgewählt wurde
|
// Zeige Spool-Buttons wenn ein Filament ausgewählt wurde
|
||||||
const selectedText = document.getElementById("selected-filament").textContent;
|
const selectedText = document.getElementById("selected-filament").textContent;
|
||||||
@@ -218,13 +218,13 @@ document.addEventListener('filamentSelected', function(event) {
|
|||||||
// Hilfsfunktion für kontrastreiche Textfarbe
|
// Hilfsfunktion für kontrastreiche Textfarbe
|
||||||
function getContrastColor(hexcolor) {
|
function getContrastColor(hexcolor) {
|
||||||
// Konvertiere Hex zu RGB
|
// Konvertiere Hex zu RGB
|
||||||
const r = parseInt(hexcolor.substr(0,2),16);
|
const r = parseInt(hexcolor.substr(0, 2), 16);
|
||||||
const g = parseInt(hexcolor.substr(2,2),16);
|
const g = parseInt(hexcolor.substr(2, 2), 16);
|
||||||
const b = parseInt(hexcolor.substr(4,2),16);
|
const b = parseInt(hexcolor.substr(4, 2), 16);
|
||||||
|
|
||||||
// Berechne Helligkeit (YIQ Formel)
|
// 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 schwarz oder weiß basierend auf Helligkeit
|
||||||
return (yiq >= 128) ? '#000000' : '#FFFFFF';
|
return (yiq >= 128) ? '#000000' : '#FFFFFF';
|
||||||
}
|
}
|
||||||
@@ -242,7 +242,7 @@ function updateNfcInfo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Finde die ausgewählte Spule in den Daten
|
// 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
|
`${spool.id} | ${spool.filament.name} (${spool.filament.material})` === selectedText
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -255,18 +255,18 @@ function updateNfcInfo() {
|
|||||||
|
|
||||||
function displayAmsData(amsData) {
|
function displayAmsData(amsData) {
|
||||||
const amsDataContainer = document.getElementById('amsData');
|
const amsDataContainer = document.getElementById('amsData');
|
||||||
amsDataContainer.innerHTML = '';
|
amsDataContainer.innerHTML = '';
|
||||||
|
|
||||||
amsData.forEach((ams) => {
|
amsData.forEach((ams) => {
|
||||||
// Bestimme den Anzeigenamen für das AMS
|
// Bestimme den Anzeigenamen für das AMS
|
||||||
const amsDisplayName = ams.ams_id === 255 ? 'External Spool' : `AMS ${ams.ams_id}`;
|
const amsDisplayName = ams.ams_id === 255 ? 'External Spool' : `AMS ${ams.ams_id}`;
|
||||||
|
|
||||||
const trayHTML = ams.tray.map(tray => {
|
const trayHTML = ams.tray.map(tray => {
|
||||||
// Prüfe ob überhaupt Daten vorhanden sind
|
// Prüfe ob überhaupt Daten vorhanden sind
|
||||||
const relevantFields = ['tray_type', 'tray_sub_brands', 'tray_info_idx', 'setting_id', 'cali_idx'];
|
const relevantFields = ['tray_type', 'tray_sub_brands', 'tray_info_idx', 'setting_id', 'cali_idx'];
|
||||||
const hasAnyContent = relevantFields.some(field =>
|
const hasAnyContent = relevantFields.some(field =>
|
||||||
tray[field] !== null &&
|
tray[field] !== null &&
|
||||||
tray[field] !== undefined &&
|
tray[field] !== undefined &&
|
||||||
tray[field] !== '' &&
|
tray[field] !== '' &&
|
||||||
tray[field] !== 'null'
|
tray[field] !== 'null'
|
||||||
);
|
);
|
||||||
@@ -282,8 +282,8 @@ function displayAmsData(amsData) {
|
|||||||
cursor: pointer; display: none;">
|
cursor: pointer; display: none;">
|
||||||
<img src="spool_in.png" alt="Spool In" style="width: 48px; height: 48px;">
|
<img src="spool_in.png" alt="Spool In" style="width: 48px; height: 48px;">
|
||||||
</button>`;
|
</button>`;
|
||||||
|
|
||||||
// Nur für nicht-leere Trays den Button-HTML erstellen
|
// Nur für nicht-leere Trays den Button-HTML erstellen
|
||||||
const outButtonHtml = `
|
const outButtonHtml = `
|
||||||
<button class="spool-button" onclick="handleSpoolOut()"
|
<button class="spool-button" onclick="handleSpoolOut()"
|
||||||
style="position: absolute; top: -35px; right: -15px;
|
style="position: absolute; top: -35px; right: -15px;
|
||||||
@@ -313,7 +313,7 @@ function displayAmsData(amsData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generiere den Type mit Color-Box zusammen
|
// 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="
|
`<p>Typ: ${tray.tray_type} ${tray.tray_color ? `<span style="
|
||||||
background-color: #${tray.tray_color};
|
background-color: #${tray.tray_color};
|
||||||
width: 20px;
|
width: 20px;
|
||||||
@@ -334,9 +334,9 @@ function displayAmsData(amsData) {
|
|||||||
|
|
||||||
// Nur gültige Felder anzeigen
|
// Nur gültige Felder anzeigen
|
||||||
const trayDetails = trayProperties
|
const trayDetails = trayProperties
|
||||||
.filter(prop =>
|
.filter(prop =>
|
||||||
tray[prop.key] !== null &&
|
tray[prop.key] !== null &&
|
||||||
tray[prop.key] !== undefined &&
|
tray[prop.key] !== undefined &&
|
||||||
tray[prop.key] !== '' &&
|
tray[prop.key] !== '' &&
|
||||||
tray[prop.key] !== 'null'
|
tray[prop.key] !== 'null'
|
||||||
)
|
)
|
||||||
@@ -350,7 +350,7 @@ function displayAmsData(amsData) {
|
|||||||
.join('');
|
.join('');
|
||||||
|
|
||||||
// Temperaturen nur anzeigen, wenn beide nicht 0 sind
|
// 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>`
|
? `<p>Nozzle Temp: ${tray.nozzle_temp_min}°C - ${tray.nozzle_temp_max}°C</p>`
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
@@ -376,7 +376,7 @@ function displayAmsData(amsData) {
|
|||||||
${trayHTML}
|
${trayHTML}
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
amsDataContainer.innerHTML += amsInfo;
|
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;
|
const selectedText = document.getElementById("selected-filament").textContent;
|
||||||
|
|
||||||
// Finde die ausgewählte Spule in den Daten
|
// 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
|
`${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
|
// 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
|
`${spool.id} | ${spool.filament.name} (${spool.filament.material})` === selectedText
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -473,7 +473,7 @@ function handleSpoolIn(amsId, trayId) {
|
|||||||
let minTemp = "175";
|
let minTemp = "175";
|
||||||
let maxTemp = "275";
|
let maxTemp = "275";
|
||||||
|
|
||||||
if (Array.isArray(selectedSpool.filament.nozzle_temperature) &&
|
if (Array.isArray(selectedSpool.filament.nozzle_temperature) &&
|
||||||
selectedSpool.filament.nozzle_temperature.length >= 2) {
|
selectedSpool.filament.nozzle_temperature.length >= 2) {
|
||||||
minTemp = selectedSpool.filament.nozzle_temperature[0];
|
minTemp = selectedSpool.filament.nozzle_temperature[0];
|
||||||
maxTemp = selectedSpool.filament.nozzle_temperature[1];
|
maxTemp = selectedSpool.filament.nozzle_temperature[1];
|
||||||
@@ -490,7 +490,7 @@ function handleSpoolIn(amsId, trayId) {
|
|||||||
nozzle_temp_max: parseInt(maxTemp),
|
nozzle_temp_max: parseInt(maxTemp),
|
||||||
type: selectedSpool.filament.material,
|
type: selectedSpool.filament.material,
|
||||||
brand: selectedSpool.filament.vendor.name,
|
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
|
cali_idx: "-1" // Default-Wert setzen
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -518,7 +518,7 @@ function handleSpoolIn(amsId, trayId) {
|
|||||||
|
|
||||||
function updateNfcStatusIndicator(data) {
|
function updateNfcStatusIndicator(data) {
|
||||||
const indicator = document.getElementById('nfcStatusIndicator');
|
const indicator = document.getElementById('nfcStatusIndicator');
|
||||||
|
|
||||||
if (data.found === 0) {
|
if (data.found === 0) {
|
||||||
// Kein NFC Tag gefunden
|
// Kein NFC Tag gefunden
|
||||||
indicator.className = 'status-circle';
|
indicator.className = 'status-circle';
|
||||||
@@ -534,7 +534,7 @@ function updateNfcStatusIndicator(data) {
|
|||||||
function updateNfcData(data) {
|
function updateNfcData(data) {
|
||||||
// Den Container für den NFC Status finden
|
// Den Container für den NFC Status finden
|
||||||
const nfcStatusContainer = document.querySelector('.nfc-status-display');
|
const nfcStatusContainer = document.querySelector('.nfc-status-display');
|
||||||
|
|
||||||
// Bestehende Daten-Anzeige entfernen falls vorhanden
|
// Bestehende Daten-Anzeige entfernen falls vorhanden
|
||||||
const existingData = nfcStatusContainer.querySelector('.nfc-data');
|
const existingData = nfcStatusContainer.querySelector('.nfc-data');
|
||||||
if (existingData) {
|
if (existingData) {
|
||||||
@@ -593,7 +593,7 @@ function updateNfcData(data) {
|
|||||||
if (matchingSpool) {
|
if (matchingSpool) {
|
||||||
// Zuerst Hersteller-Dropdown aktualisieren
|
// Zuerst Hersteller-Dropdown aktualisieren
|
||||||
document.getElementById("vendorSelect").value = matchingSpool.filament.vendor.id;
|
document.getElementById("vendorSelect").value = matchingSpool.filament.vendor.id;
|
||||||
|
|
||||||
// Dann Filament-Dropdown aktualisieren und Spule auswählen
|
// Dann Filament-Dropdown aktualisieren und Spule auswählen
|
||||||
updateFilamentDropdown();
|
updateFilamentDropdown();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -606,7 +606,7 @@ function updateNfcData(data) {
|
|||||||
html += '</div>';
|
html += '</div>';
|
||||||
nfcDataDiv.innerHTML = html;
|
nfcDataDiv.innerHTML = html;
|
||||||
|
|
||||||
|
|
||||||
// Neues div zum Container hinzufügen
|
// Neues div zum Container hinzufügen
|
||||||
nfcStatusContainer.appendChild(nfcDataDiv);
|
nfcStatusContainer.appendChild(nfcDataDiv);
|
||||||
}
|
}
|
||||||
@@ -619,7 +619,7 @@ function writeNfcTag() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const spoolsData = window.getSpoolData();
|
const spoolsData = window.getSpoolData();
|
||||||
const selectedSpool = spoolsData.find(spool =>
|
const selectedSpool = spoolsData.find(spool =>
|
||||||
`${spool.id} | ${spool.filament.name} (${spool.filament.material})` === selectedText
|
`${spool.id} | ${spool.filament.name} (${spool.filament.material})` === selectedText
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -631,8 +631,8 @@ function writeNfcTag() {
|
|||||||
// Temperaturwerte korrekt extrahieren
|
// Temperaturwerte korrekt extrahieren
|
||||||
let minTemp = "175";
|
let minTemp = "175";
|
||||||
let maxTemp = "275";
|
let maxTemp = "275";
|
||||||
|
|
||||||
if (Array.isArray(selectedSpool.filament.nozzle_temperature) &&
|
if (Array.isArray(selectedSpool.filament.nozzle_temperature) &&
|
||||||
selectedSpool.filament.nozzle_temperature.length >= 2) {
|
selectedSpool.filament.nozzle_temperature.length >= 2) {
|
||||||
minTemp = String(selectedSpool.filament.nozzle_temperature[0]);
|
minTemp = String(selectedSpool.filament.nozzle_temperature[0]);
|
||||||
maxTemp = String(selectedSpool.filament.nozzle_temperature[1]);
|
maxTemp = String(selectedSpool.filament.nozzle_temperature[1]);
|
||||||
@@ -685,5 +685,4 @@ function showNotification(message, isSuccess) {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
notification.remove();
|
notification.remove();
|
||||||
}, 300);
|
}, 300);
|
||||||
}, 3000);
|
}, 3000);}
|
||||||
}
|
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
<!-- 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>
|
||||||
+33
-2
@@ -57,6 +57,31 @@
|
|||||||
toggleOctoFields();
|
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() {
|
function checkSpoolmanInstance() {
|
||||||
const url = document.getElementById('spoolmanUrl').value;
|
const url = document.getElementById('spoolmanUrl').value;
|
||||||
const spoolmanOctoEnabled = document.getElementById('spoolmanOctoEnabled').checked;
|
const spoolmanOctoEnabled = document.getElementById('spoolmanOctoEnabled').checked;
|
||||||
@@ -89,7 +114,12 @@
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.healthy) {
|
if (data.healthy) {
|
||||||
document.getElementById('bambuStatusMessage').innerText = 'Bambu Credentials saved!';
|
document.getElementById('bambuStatusMessage').innerText = 'Bambu Credentials saved!';
|
||||||
} else {
|
// Reload with forced cache refresh after short delay
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.reload(true);
|
||||||
|
window.location.href = '/';
|
||||||
|
}, 1500);
|
||||||
|
} else {
|
||||||
document.getElementById('bambuStatusMessage').innerText = 'Error while saving Bambu Credentials.';
|
document.getElementById('bambuStatusMessage').innerText = 'Error while saving Bambu Credentials.';
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -162,7 +192,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button style="margin: 0;" onclick="saveBambuCredentials()">Save Bambu Credentials</button>
|
<button style="margin: 0;" onclick="saveBambuCredentials()">Save Bambu Credentials</button>
|
||||||
<p id="bambuStatusMessage"></p>
|
<button style="margin: 0; background-color: red;" onclick="removeBambuCredentials()">Remove Credentials</button>
|
||||||
|
<p id="bambuStatusMessage"></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+7
-12
@@ -147,6 +147,13 @@ function updateFilamentDropdown(selectedSmId = null) {
|
|||||||
|
|
||||||
if (vendorId) {
|
if (vendorId) {
|
||||||
const filteredFilaments = spoolsData.filter(spool => {
|
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 &&
|
const hasValidNfcId = spool.extra &&
|
||||||
spool.extra.nfc_id &&
|
spool.extra.nfc_id &&
|
||||||
spool.extra.nfc_id !== '""' &&
|
spool.extra.nfc_id !== '""' &&
|
||||||
@@ -240,18 +247,6 @@ 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
|
// Event Listener
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
initSpoolman();
|
initSpoolman();
|
||||||
|
|||||||
@@ -129,6 +129,7 @@
|
|||||||
if (data.status === 'success' || lastReceivedProgress >= 98) {
|
if (data.status === 'success' || lastReceivedProgress >= 98) {
|
||||||
clearTimeout(wsReconnectTimer);
|
clearTimeout(wsReconnectTimer);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
window.location.reload(true);
|
||||||
window.location.href = '/';
|
window.location.href = '/';
|
||||||
}, 30000);
|
}, 30000);
|
||||||
}
|
}
|
||||||
@@ -164,6 +165,7 @@
|
|||||||
status.className = 'status success';
|
status.className = 'status success';
|
||||||
status.style.display = 'block';
|
status.style.display = 'block';
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
window.location.reload(true);
|
||||||
window.location.href = '/';
|
window.location.href = '/';
|
||||||
}, 30000);
|
}, 30000);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,8 @@
|
|||||||
<h5 class="card-title">Sacle Calibration</h5>
|
<h5 class="card-title">Sacle Calibration</h5>
|
||||||
<button id="calibrateBtn" class="btn btn-primary">Calibrate Scale</button>
|
<button id="calibrateBtn" class="btn btn-primary">Calibrate Scale</button>
|
||||||
<button id="tareBtn" class="btn btn-secondary">Tare Scale</button>
|
<button id="tareBtn" class="btn btn-secondary">Tare Scale</button>
|
||||||
|
Enable Auto-TARE <input type="checkbox" id="autoTareCheckbox" onchange="setAutoTare(this.checked);"
|
||||||
|
{{autoTare}}>
|
||||||
<div id="statusMessage" class="mt-3"></div>
|
<div id="statusMessage" class="mt-3"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -139,6 +141,14 @@
|
|||||||
payload: 'tare'
|
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
|
// WebSocket-Verbindung beim Laden der Seite initiieren
|
||||||
connectWebSocket();
|
connectWebSocket();
|
||||||
|
|||||||
+2
-2
@@ -9,8 +9,8 @@
|
|||||||
; https://docs.platformio.org/page/projectconf.html
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
[common]
|
[common]
|
||||||
version = "1.4.1"
|
version = "0.2.1"
|
||||||
to_old_version = "1.4.0"
|
to_old_version = "0.2.0"
|
||||||
|
|
||||||
##
|
##
|
||||||
[env:esp32dev]
|
[env:esp32dev]
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ def copy_file(input_file, output_file):
|
|||||||
|
|
||||||
def should_compress(file):
|
def should_compress(file):
|
||||||
# Skip compression for spoolman.html
|
# Skip compression for spoolman.html
|
||||||
if file == 'spoolman.html':
|
if file == 'spoolman.html' or file == 'waage.html':
|
||||||
return False
|
return False
|
||||||
# Komprimiere nur bestimmte Dateitypen
|
# Komprimiere nur bestimmte Dateitypen
|
||||||
return file.endswith(('.js', '.png', '.css', '.html'))
|
return file.endswith(('.js', '.png', '.css', '.html'))
|
||||||
|
|||||||
+16
-5
@@ -3,7 +3,7 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include "commonFS.h"
|
#include "commonFS.h"
|
||||||
|
|
||||||
bool spoolman_connected = false;
|
volatile spoolmanApiStateType spoolmanApiState = API_INIT;
|
||||||
String spoolmanUrl = "";
|
String spoolmanUrl = "";
|
||||||
bool octoEnabled = false;
|
bool octoEnabled = false;
|
||||||
String octoUrl = "";
|
String octoUrl = "";
|
||||||
@@ -85,7 +85,8 @@ JsonDocument fetchSingleSpoolInfo(int spoolId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sendToApi(void *parameter) {
|
void sendToApi(void *parameter) {
|
||||||
SendToApiParams* params = (SendToApiParams*)parameter;
|
spoolmanApiState = API_TRANSMITTING;
|
||||||
|
SendToApiParams *params = (SendToApiParams *)parameter;
|
||||||
|
|
||||||
// Extrahiere die Werte
|
// Extrahiere die Werte
|
||||||
String httpType = params->httpType;
|
String httpType = params->httpType;
|
||||||
@@ -94,13 +95,17 @@ void sendToApi(void *parameter) {
|
|||||||
String octoToken = params->octoToken;
|
String octoToken = params->octoToken;
|
||||||
|
|
||||||
HTTPClient http;
|
HTTPClient http;
|
||||||
|
http.setReuse(false);
|
||||||
http.begin(spoolsUrl);
|
http.begin(spoolsUrl);
|
||||||
http.addHeader("Content-Type", "application/json");
|
http.addHeader("Content-Type", "application/json");
|
||||||
if (octoEnabled && octoToken != "") http.addHeader("X-Api-Key", octoToken);
|
if (octoEnabled && octoToken != "") http.addHeader("X-Api-Key", octoToken);
|
||||||
|
|
||||||
int httpCode = http.PUT(updatePayload);
|
int httpCode;
|
||||||
if (httpType == "PATCH") httpCode = http.PATCH(updatePayload);
|
if (httpType == "PATCH") httpCode = http.PATCH(updatePayload);
|
||||||
if (httpType == "POST") httpCode = http.POST(updatePayload);
|
else if (httpType == "POST")
|
||||||
|
httpCode = http.POST(updatePayload);
|
||||||
|
else
|
||||||
|
httpCode = http.PUT(updatePayload);
|
||||||
|
|
||||||
if (httpCode == HTTP_CODE_OK) {
|
if (httpCode == HTTP_CODE_OK) {
|
||||||
Serial.println("Spoolman erfolgreich aktualisiert");
|
Serial.println("Spoolman erfolgreich aktualisiert");
|
||||||
@@ -111,10 +116,12 @@ void sendToApi(void *parameter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
http.end();
|
http.end();
|
||||||
|
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
// Speicher freigeben
|
// Speicher freigeben
|
||||||
delete params;
|
delete params;
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
|
spoolmanApiState = API_IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool updateSpoolTagId(String uidString, const char* payload) {
|
bool updateSpoolTagId(String uidString, const char* payload) {
|
||||||
@@ -164,6 +171,7 @@ bool updateSpoolTagId(String uidString, const char* payload) {
|
|||||||
0, // Priorität
|
0, // Priorität
|
||||||
NULL // Task-Handle (nicht benötigt)
|
NULL // Task-Handle (nicht benötigt)
|
||||||
);
|
);
|
||||||
|
updateDoc.clear();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -200,6 +208,7 @@ uint8_t updateSpoolWeight(String spoolId, uint16_t weight) {
|
|||||||
0, // Priorität
|
0, // Priorität
|
||||||
NULL // Task-Handle (nicht benötigt)
|
NULL // Task-Handle (nicht benötigt)
|
||||||
);
|
);
|
||||||
|
updateDoc.clear();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -237,6 +246,7 @@ bool updateSpoolOcto(int spoolId) {
|
|||||||
0, // Priorität
|
0, // Priorität
|
||||||
NULL // Task-Handle (nicht benötigt)
|
NULL // Task-Handle (nicht benötigt)
|
||||||
);
|
);
|
||||||
|
updateDoc.clear();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -469,7 +479,8 @@ bool checkSpoolmanInstance(const String& url) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
spoolman_connected = true;
|
spoolmanApiState = API_IDLE;
|
||||||
|
oledShowTopRow();
|
||||||
return strcmp(status, "healthy") == 0;
|
return strcmp(status, "healthy") == 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,14 @@
|
|||||||
#include "website.h"
|
#include "website.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
API_INIT,
|
||||||
|
API_IDLE,
|
||||||
|
API_TRANSMITTING
|
||||||
|
} spoolmanApiStateType;
|
||||||
|
|
||||||
|
extern volatile spoolmanApiStateType spoolmanApiState;
|
||||||
extern bool spoolman_connected;
|
extern bool spoolman_connected;
|
||||||
extern String spoolmanUrl;
|
extern String spoolmanUrl;
|
||||||
extern bool octoEnabled;
|
extern bool octoEnabled;
|
||||||
|
|||||||
+196
-53
@@ -18,7 +18,7 @@ PubSubClient client(sslClient);
|
|||||||
TaskHandle_t BambuMqttTask;
|
TaskHandle_t BambuMqttTask;
|
||||||
|
|
||||||
String report_topic = "";
|
String report_topic = "";
|
||||||
//String request_topic = "";
|
String request_topic = "";
|
||||||
const char* bambu_username = "bblp";
|
const char* bambu_username = "bblp";
|
||||||
const char* bambu_ip = nullptr;
|
const char* bambu_ip = nullptr;
|
||||||
const char* bambu_accesscode = nullptr;
|
const char* bambu_accesscode = nullptr;
|
||||||
@@ -27,6 +27,7 @@ const char* bambu_serialnr = nullptr;
|
|||||||
String g_bambu_ip = "";
|
String g_bambu_ip = "";
|
||||||
String g_bambu_accesscode = "";
|
String g_bambu_accesscode = "";
|
||||||
String g_bambu_serialnr = "";
|
String g_bambu_serialnr = "";
|
||||||
|
bool bambuDisabled = false;
|
||||||
|
|
||||||
bool bambu_connected = false;
|
bool bambu_connected = false;
|
||||||
bool autoSendToBambu = false;
|
bool autoSendToBambu = false;
|
||||||
@@ -37,6 +38,35 @@ int ams_count = 0;
|
|||||||
String amsJsonData; // Speichert das fertige JSON für WebSocket-Clients
|
String amsJsonData; // Speichert das fertige JSON für WebSocket-Clients
|
||||||
AMSData ams_data[MAX_AMS]; // Definition des Arrays;
|
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) {
|
bool saveBambuCredentials(const String& ip, const String& serialnr, const String& accesscode, bool autoSend, const String& autoSendTime) {
|
||||||
if (BambuMqttTask) {
|
if (BambuMqttTask) {
|
||||||
vTaskDelete(BambuMqttTask);
|
vTaskDelete(BambuMqttTask);
|
||||||
@@ -92,7 +122,7 @@ bool loadBambuCredentials() {
|
|||||||
bambu_serialnr = g_bambu_serialnr.c_str();
|
bambu_serialnr = g_bambu_serialnr.c_str();
|
||||||
|
|
||||||
report_topic = "device/" + String(bambu_serialnr) + "/report";
|
report_topic = "device/" + String(bambu_serialnr) + "/report";
|
||||||
//request_topic = "device/" + String(bambu_serialnr) + "/request";
|
request_topic = "device/" + String(bambu_serialnr) + "/request";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Serial.println("Keine gültigen Bambu-Credentials gefunden.");
|
Serial.println("Keine gültigen Bambu-Credentials gefunden.");
|
||||||
@@ -197,44 +227,104 @@ FilamentResult findFilamentIdx(String brand, String type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool sendMqttMessage(const String& payload) {
|
bool sendMqttMessage(const String& payload) {
|
||||||
Serial.println("Sending MQTT message");
|
// Check MQTT client state first
|
||||||
Serial.println(payload);
|
if (!client.connected()) {
|
||||||
if (client.publish(report_topic.c_str(), payload.c_str()))
|
Serial.println("Error: MQTT client not connected when trying to send message");
|
||||||
{
|
Serial.print("MQTT client state: ");
|
||||||
return true;
|
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) {
|
bool setBambuSpool(String payload) {
|
||||||
Serial.println("Spool settings in");
|
Serial.println("Spool settings received from WebSocket");
|
||||||
Serial.println(payload);
|
Serial.println(payload);
|
||||||
|
|
||||||
// Parse the JSON
|
// Parse the JSON
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
DeserializationError error = deserializeJson(doc, payload);
|
DeserializationError error = deserializeJson(doc, payload);
|
||||||
if (error) {
|
if (error) {
|
||||||
Serial.print("Error parsing JSON: ");
|
Serial.print("Error parsing setBambuSpool-JSON: ");
|
||||||
Serial.println(error.c_str());
|
Serial.println(error.c_str());
|
||||||
|
Serial.print("Free Heap-Memory: ");
|
||||||
|
Serial.println(ESP.getFreeHeap());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int amsId = doc["amsId"];
|
// Check if we have all required fields
|
||||||
int trayId = doc["trayId"];
|
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>();
|
String color = doc["color"].as<String>();
|
||||||
color.toUpperCase();
|
color.toUpperCase();
|
||||||
int minTemp = doc["nozzle_temp_min"];
|
int minTemp = doc["nozzle_temp_min"] | 0; // Default to 0 if not present
|
||||||
int maxTemp = doc["nozzle_temp_max"];
|
int maxTemp = doc["nozzle_temp_max"] | 0; // Default to 0 if not present
|
||||||
String type = doc["type"].as<String>();
|
String type = doc["type"] | ""; // Default to empty string if not present
|
||||||
(type == "PLA+") ? type = "PLA" : type;
|
(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>() : "";
|
String tray_info_idx = (doc["tray_info_idx"].as<String>() != "-1") ? doc["tray_info_idx"].as<String>() : "";
|
||||||
if (tray_info_idx == "") {
|
if (tray_info_idx == "") {
|
||||||
if (brand != "" && type != "") {
|
if (brand != "" && type != "") {
|
||||||
FilamentResult result = findFilamentIdx(brand, type);
|
FilamentResult result = findFilamentIdx(brand, type);
|
||||||
tray_info_idx = result.key;
|
tray_info_idx = result.key;
|
||||||
type = result.type; // Aktualisiere den type mit dem gefundenen Basistyp
|
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>();
|
String setting_id = doc["bambu_setting_id"].as<String>();
|
||||||
@@ -242,6 +332,7 @@ bool setBambuSpool(String payload) {
|
|||||||
|
|
||||||
doc.clear();
|
doc.clear();
|
||||||
|
|
||||||
|
// Create MQTT message
|
||||||
doc["print"]["sequence_id"] = "0";
|
doc["print"]["sequence_id"] = "0";
|
||||||
doc["print"]["command"] = "ams_filament_setting";
|
doc["print"]["command"] = "ams_filament_setting";
|
||||||
doc["print"]["ams_id"] = amsId < 200 ? amsId : 255;
|
doc["print"]["ams_id"] = amsId < 200 ? amsId : 255;
|
||||||
@@ -250,26 +341,25 @@ bool setBambuSpool(String payload) {
|
|||||||
doc["print"]["nozzle_temp_min"] = minTemp;
|
doc["print"]["nozzle_temp_min"] = minTemp;
|
||||||
doc["print"]["nozzle_temp_max"] = maxTemp;
|
doc["print"]["nozzle_temp_max"] = maxTemp;
|
||||||
doc["print"]["tray_type"] = type;
|
doc["print"]["tray_type"] = type;
|
||||||
//doc["print"]["cali_idx"] = (cali_idx != "") ? cali_idx : "";
|
|
||||||
doc["print"]["tray_info_idx"] = tray_info_idx;
|
doc["print"]["tray_info_idx"] = tray_info_idx;
|
||||||
doc["print"]["setting_id"] = setting_id;
|
doc["print"]["setting_id"] = setting_id;
|
||||||
|
|
||||||
// Serialize the JSON
|
// Serialize and send MQTT message
|
||||||
String output;
|
String output;
|
||||||
serializeJson(doc, output);
|
serializeJson(doc, output);
|
||||||
|
Serial.println("Sending to Bambu printer:");
|
||||||
|
Serial.println(output);
|
||||||
|
|
||||||
if (sendMqttMessage(output)) {
|
if (!sendMqttMessage(output)) {
|
||||||
Serial.println("Spool successfully set");
|
Serial.println("Failed to send filament settings to printer");
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Serial.println("Failed to set spool");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Serial.println("Filament settings sent successfully");
|
||||||
doc.clear();
|
doc.clear();
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
|
// Send calibration if available
|
||||||
if (cali_idx != "") {
|
if (cali_idx != "") {
|
||||||
yield();
|
yield();
|
||||||
doc["print"]["sequence_id"] = "0";
|
doc["print"]["sequence_id"] = "0";
|
||||||
@@ -278,21 +368,18 @@ bool setBambuSpool(String payload) {
|
|||||||
doc["print"]["nozzle_diameter"] = "0.4";
|
doc["print"]["nozzle_diameter"] = "0.4";
|
||||||
doc["print"]["cali_idx"] = cali_idx.toInt();
|
doc["print"]["cali_idx"] = cali_idx.toInt();
|
||||||
doc["print"]["tray_id"] = trayId < 200 ? trayId : 254;
|
doc["print"]["tray_id"] = trayId < 200 ? trayId : 254;
|
||||||
//doc["print"]["ams_id"] = amsId < 200 ? amsId : 255;
|
|
||||||
|
|
||||||
// Serialize the JSON
|
|
||||||
String output;
|
String output;
|
||||||
serializeJson(doc, output);
|
serializeJson(doc, output);
|
||||||
|
Serial.println("Sending calibration to printer:");
|
||||||
|
Serial.println(output);
|
||||||
|
|
||||||
if (sendMqttMessage(output)) {
|
if (!sendMqttMessage(output)) {
|
||||||
Serial.println("Extrusion calibration successfully set");
|
Serial.println("Failed to send calibration settings to printer");
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Serial.println("Failed to set extrusion calibration");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Serial.println("Calibration settings sent successfully");
|
||||||
doc.clear();
|
doc.clear();
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
@@ -420,7 +507,9 @@ void mqtt_callback(char* topic, byte* payload, unsigned int length) {
|
|||||||
message = "";
|
message = "";
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
Serial.print("Fehler beim Parsen des JSON: ");
|
Serial.print("Free Heap-Memory: ");
|
||||||
|
Serial.println(ESP.getFreeHeap());
|
||||||
|
Serial.print("Error parsing MQTT-JSON: ");
|
||||||
Serial.println(error.c_str());
|
Serial.println(error.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -549,20 +638,47 @@ void reconnect() {
|
|||||||
uint8_t retries = 0;
|
uint8_t retries = 0;
|
||||||
while (!client.connected()) {
|
while (!client.connected()) {
|
||||||
Serial.println("Attempting MQTT re/connection...");
|
Serial.println("Attempting MQTT re/connection...");
|
||||||
|
Serial.print("State before connect: ");
|
||||||
|
Serial.println(client.state());
|
||||||
bambu_connected = false;
|
bambu_connected = false;
|
||||||
oledShowTopRow();
|
oledShowTopRow();
|
||||||
|
|
||||||
// Attempt to connect
|
// Generate a random client ID suffix
|
||||||
if (client.connect(bambu_serialnr, bambu_username, bambu_accesscode)) {
|
String clientId = String(bambu_serialnr) + "_" + String(random(0xffff), HEX);
|
||||||
Serial.println("MQTT re/connected");
|
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;
|
bambu_connected = true;
|
||||||
oledShowTopRow();
|
oledShowTopRow();
|
||||||
} else {
|
} else {
|
||||||
|
int state = client.state();
|
||||||
Serial.print("failed, rc=");
|
Serial.print("failed, rc=");
|
||||||
Serial.print(client.state());
|
Serial.print(state);
|
||||||
Serial.println(" try again in 5 seconds");
|
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;
|
bambu_connected = false;
|
||||||
oledShowTopRow();
|
oledShowTopRow();
|
||||||
|
|
||||||
@@ -570,11 +686,9 @@ void reconnect() {
|
|||||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||||
if (retries > 5) {
|
if (retries > 5) {
|
||||||
Serial.println("Disable Bambu MQTT Task after 5 retries");
|
Serial.println("Disable Bambu MQTT Task after 5 retries");
|
||||||
//vTaskSuspend(BambuMqttTask);
|
|
||||||
vTaskDelete(BambuMqttTask);
|
vTaskDelete(BambuMqttTask);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
retries++;
|
retries++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -582,17 +696,34 @@ void reconnect() {
|
|||||||
|
|
||||||
void mqtt_loop(void * parameter) {
|
void mqtt_loop(void * parameter) {
|
||||||
Serial.println("Bambu MQTT Task gestartet");
|
Serial.println("Bambu MQTT Task gestartet");
|
||||||
|
unsigned long lastCheck = 0;
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if (pauseBambuMqttTask) {
|
if (pauseBambuMqttTask) {
|
||||||
vTaskDelay(10000);
|
vTaskDelay(10000);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned long now = millis();
|
||||||
|
|
||||||
if (!client.connected()) {
|
if (!client.connected()) {
|
||||||
|
Serial.println("Connection lost, attempting reconnect...");
|
||||||
reconnect();
|
reconnect();
|
||||||
yield();
|
yield();
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
vTaskDelay(100);
|
vTaskDelay(100);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Periodically check connection status
|
||||||
|
if (now - lastCheck > 60000) { // Check every 60 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();
|
client.loop();
|
||||||
yield();
|
yield();
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
@@ -605,26 +736,41 @@ bool setupMqtt() {
|
|||||||
bool success = loadBambuCredentials();
|
bool success = loadBambuCredentials();
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
Serial.println("Failed to load Bambu credentials");
|
bambuDisabled = true;
|
||||||
oledShowMessage("Bambu Credentials Missing");
|
|
||||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success && bambu_ip != "" && bambu_accesscode != "" && bambu_serialnr != "")
|
if (success && bambu_ip != "" && bambu_accesscode != "" && bambu_serialnr != "")
|
||||||
{
|
{
|
||||||
|
bambuDisabled = false;
|
||||||
sslClient.setCACert(root_ca);
|
sslClient.setCACert(root_ca);
|
||||||
sslClient.setInsecure();
|
sslClient.setInsecure();
|
||||||
client.setServer(bambu_ip, 8883);
|
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
|
// Verbinden mit dem MQTT-Server
|
||||||
bool connected = true;
|
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.setCallback(mqtt_callback);
|
||||||
client.setBufferSize(5120);
|
client.setBufferSize(16384); // Increased to 16KB to handle larger JSON
|
||||||
client.subscribe(report_topic.c_str());
|
|
||||||
//client.subscribe(request_topic.c_str());
|
// Subscribe with QoS 1
|
||||||
|
if (client.subscribe(report_topic.c_str(), 1)) {
|
||||||
|
Serial.println("Successfully subscribed to topic with QoS 1: " + report_topic);
|
||||||
|
} else {
|
||||||
|
Serial.println("Failed to subscribe to topic: " + report_topic);
|
||||||
|
}
|
||||||
|
|
||||||
Serial.println("MQTT-Client initialisiert");
|
Serial.println("MQTT-Client initialisiert");
|
||||||
|
|
||||||
oledShowMessage("Bambu Connected");
|
oledShowMessage("Bambu Connected");
|
||||||
@@ -634,7 +780,7 @@ bool setupMqtt() {
|
|||||||
xTaskCreatePinnedToCore(
|
xTaskCreatePinnedToCore(
|
||||||
mqtt_loop, /* Function to implement the task */
|
mqtt_loop, /* Function to implement the task */
|
||||||
"BambuMqtt", /* Name of the task */
|
"BambuMqtt", /* Name of the task */
|
||||||
8192, /* Stack size in words */
|
16384, /* Stack size in words */
|
||||||
NULL, /* Task input parameter */
|
NULL, /* Task input parameter */
|
||||||
mqttTaskPrio, /* Priority of the task */
|
mqttTaskPrio, /* Priority of the task */
|
||||||
&BambuMqttTask, /* Task handle. */
|
&BambuMqttTask, /* Task handle. */
|
||||||
@@ -653,10 +799,7 @@ bool setupMqtt() {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Serial.println("Fehler: Keine MQTT-Daten vorhanden");
|
bambuDisabled = true;
|
||||||
oledShowMessage("Bambu Credentials Missing");
|
|
||||||
oledShowTopRow();
|
|
||||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -30,7 +30,9 @@ extern int ams_count;
|
|||||||
extern AMSData ams_data[MAX_AMS];
|
extern AMSData ams_data[MAX_AMS];
|
||||||
extern bool autoSendToBambu;
|
extern bool autoSendToBambu;
|
||||||
extern int autoSetToBambuSpoolId;
|
extern int autoSetToBambuSpoolId;
|
||||||
|
extern bool bambuDisabled;
|
||||||
|
|
||||||
|
bool removeBambuCredentials();
|
||||||
bool loadBambuCredentials();
|
bool loadBambuCredentials();
|
||||||
bool saveBambuCredentials(const String& bambu_ip, const String& bambu_serialnr, const String& bambu_accesscode, const bool autoSend, const String& autoSendTime);
|
bool saveBambuCredentials(const String& bambu_ip, const String& bambu_serialnr, const String& bambu_accesscode, const bool autoSend, const String& autoSendTime);
|
||||||
bool setupMqtt();
|
bool setupMqtt();
|
||||||
|
|||||||
@@ -1,6 +1,23 @@
|
|||||||
#include "commonFS.h"
|
#include "commonFS.h"
|
||||||
#include <LittleFS.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) {
|
bool saveJsonValue(const char* filename, const JsonDocument& doc) {
|
||||||
File file = LittleFS.open(filename, "w");
|
File file = LittleFS.open(filename, "w");
|
||||||
if (!file) {
|
if (!file) {
|
||||||
|
|||||||
+2
-1
@@ -5,7 +5,8 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <LittleFS.h>
|
#include <LittleFS.h>
|
||||||
|
|
||||||
bool saveJsonValue(const char* filename, const JsonDocument& doc);
|
bool removeJsonValue(const char *filename);
|
||||||
|
bool saveJsonValue(const char *filename, const JsonDocument &doc);
|
||||||
bool loadJsonValue(const char* filename, JsonDocument& doc);
|
bool loadJsonValue(const char* filename, JsonDocument& doc);
|
||||||
void initializeFileSystem();
|
void initializeFileSystem();
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,11 @@ const uint16_t SCALE_LEVEL_WEIGHT = 500;
|
|||||||
uint16_t defaultScaleCalibrationValue = 430;
|
uint16_t defaultScaleCalibrationValue = 430;
|
||||||
// ***** HX711
|
// ***** HX711
|
||||||
|
|
||||||
|
// ***** TTP223 (Touch Sensor)
|
||||||
|
// TTP223 circuit wiring
|
||||||
|
const uint8_t TTP223_PIN = 25;
|
||||||
|
// ***** TTP223
|
||||||
|
|
||||||
// ***** Display
|
// ***** Display
|
||||||
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
|
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
|
||||||
// On an ESP32: 21(SDA), 22(SCL)
|
// On an ESP32: 21(SDA), 22(SCL)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ extern const uint8_t LOADCELL_DOUT_PIN;
|
|||||||
extern const uint8_t LOADCELL_SCK_PIN;
|
extern const uint8_t LOADCELL_SCK_PIN;
|
||||||
extern const uint8_t calVal_eepromAdress;
|
extern const uint8_t calVal_eepromAdress;
|
||||||
extern const uint16_t SCALE_LEVEL_WEIGHT;
|
extern const uint16_t SCALE_LEVEL_WEIGHT;
|
||||||
|
extern const uint8_t TTP223_PIN;
|
||||||
|
|
||||||
extern const int8_t OLED_RESET;
|
extern const int8_t OLED_RESET;
|
||||||
extern const uint8_t SCREEN_ADDRESS;
|
extern const uint8_t SCREEN_ADDRESS;
|
||||||
|
|||||||
+6
-3
@@ -177,9 +177,12 @@ void oledShowTopRow() {
|
|||||||
display.drawBitmap(50, 0, bitmap_off , 16, 16, WHITE);
|
display.drawBitmap(50, 0, bitmap_off , 16, 16, WHITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spoolman_connected == 1) {
|
if (spoolmanApiState != API_INIT)
|
||||||
display.drawBitmap(80, 0, bitmap_spoolman_on , 16, 16, WHITE);
|
{
|
||||||
} else {
|
display.drawBitmap(80, 0, bitmap_spoolman_on, 16, 16, WHITE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
display.drawBitmap(80, 0, bitmap_off , 16, 16, WHITE);
|
display.drawBitmap(80, 0, bitmap_off , 16, 16, WHITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+40
-21
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
bool mainTaskWasPaused = 0;
|
bool mainTaskWasPaused = 0;
|
||||||
uint8_t scaleTareCounter = 0;
|
uint8_t scaleTareCounter = 0;
|
||||||
|
bool touchSensorConnected = false;
|
||||||
|
|
||||||
// ##### SETUP #####
|
// ##### SETUP #####
|
||||||
void setup() {
|
void setup() {
|
||||||
@@ -39,7 +40,6 @@ void setup() {
|
|||||||
setupWebserver(server);
|
setupWebserver(server);
|
||||||
|
|
||||||
// Spoolman API
|
// Spoolman API
|
||||||
// api.cpp
|
|
||||||
initSpoolman();
|
initSpoolman();
|
||||||
|
|
||||||
// Bambu MQTT
|
// Bambu MQTT
|
||||||
@@ -48,7 +48,16 @@ void setup() {
|
|||||||
// NFC Reader
|
// NFC Reader
|
||||||
startNfc();
|
startNfc();
|
||||||
|
|
||||||
start_scale();
|
// Touch Sensor
|
||||||
|
pinMode(TTP223_PIN, INPUT_PULLUP);
|
||||||
|
if (digitalRead(TTP223_PIN) == LOW)
|
||||||
|
{
|
||||||
|
Serial.println("Touch Sensor is connected");
|
||||||
|
touchSensorConnected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scale
|
||||||
|
start_scale(touchSensorConnected);
|
||||||
|
|
||||||
// WDT initialisieren mit 10 Sekunden Timeout
|
// WDT initialisieren mit 10 Sekunden Timeout
|
||||||
bool panic = true; // Wenn true, löst ein WDT-Timeout einen System-Panik aus
|
bool panic = true; // Wenn true, löst ein WDT-Timeout einen System-Panik aus
|
||||||
@@ -84,13 +93,25 @@ uint8_t autoAmsCounter = 0;
|
|||||||
uint8_t weightSend = 0;
|
uint8_t weightSend = 0;
|
||||||
int16_t lastWeight = 0;
|
int16_t lastWeight = 0;
|
||||||
|
|
||||||
|
// WIFI check variables
|
||||||
unsigned long lastWifiCheckTime = 0;
|
unsigned long lastWifiCheckTime = 0;
|
||||||
const unsigned long wifiCheckInterval = 60000; // Überprüfe alle 60 Sekunden (60000 ms)
|
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 #####
|
// ##### PROGRAM START #####
|
||||||
void loop() {
|
void loop() {
|
||||||
unsigned long currentMillis = millis();
|
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
|
// Überprüfe regelmäßig die WLAN-Verbindung
|
||||||
if (intervalElapsed(currentMillis, lastWifiCheckTime, wifiCheckInterval)) {
|
if (intervalElapsed(currentMillis, lastWifiCheckTime, wifiCheckInterval)) {
|
||||||
checkWiFiConnection();
|
checkWiFiConnection();
|
||||||
@@ -98,9 +119,14 @@ void loop() {
|
|||||||
|
|
||||||
// Wenn Bambu auto set Spool aktiv
|
// Wenn Bambu auto set Spool aktiv
|
||||||
if (autoSendToBambu && autoSetToBambuSpoolId > 0) {
|
if (autoSendToBambu && autoSetToBambuSpoolId > 0) {
|
||||||
|
if (!bambuDisabled && !bambu_connected)
|
||||||
|
|
||||||
|
{
|
||||||
|
bambu_restart();
|
||||||
|
}
|
||||||
if (intervalElapsed(currentMillis, lastAutoSetBambuAmsTime, autoSetBambuAmsInterval))
|
if (intervalElapsed(currentMillis, lastAutoSetBambuAmsTime, autoSetBambuAmsInterval))
|
||||||
{
|
{
|
||||||
if (hasReadRfidTag == 0)
|
if (nfcReaderState == NFC_IDLE)
|
||||||
{
|
{
|
||||||
lastAutoSetBambuAmsTime = currentMillis;
|
lastAutoSetBambuAmsTime = currentMillis;
|
||||||
oledShowMessage("Auto Set " + String(autoSetBambuAmsCounter - autoAmsCounter) + "s");
|
oledShowMessage("Auto Set " + String(autoSetBambuAmsCounter - autoAmsCounter) + "s");
|
||||||
@@ -134,7 +160,7 @@ void loop() {
|
|||||||
// Ausgabe der Waage auf Display
|
// Ausgabe der Waage auf Display
|
||||||
if(pauseMainTask == 0)
|
if(pauseMainTask == 0)
|
||||||
{
|
{
|
||||||
if (mainTaskWasPaused || (weight != lastWeight && hasReadRfidTag == 0 && (!autoSendToBambu || autoSetToBambuSpoolId == 0)))
|
if (mainTaskWasPaused || (weight != lastWeight && nfcReaderState == NFC_IDLE && (!autoSendToBambu || autoSetToBambuSpoolId == 0)))
|
||||||
{
|
{
|
||||||
(weight < 2) ? ((weight < -2) ? oledShowMessage("!! -0") : oledShowWeight(0)) : oledShowWeight(weight);
|
(weight < 2) ? ((weight < -2) ? oledShowMessage("!! -0") : oledShowWeight(0)) : oledShowWeight(weight);
|
||||||
}
|
}
|
||||||
@@ -147,27 +173,18 @@ void loop() {
|
|||||||
|
|
||||||
|
|
||||||
// Wenn Timer abgelaufen und nicht gerade ein RFID-Tag geschrieben wird
|
// Wenn Timer abgelaufen und nicht gerade ein RFID-Tag geschrieben wird
|
||||||
if (currentMillis - lastWeightReadTime >= weightReadInterval && hasReadRfidTag < 3)
|
if (currentMillis - lastWeightReadTime >= weightReadInterval && nfcReaderState < NFC_WRITING)
|
||||||
{
|
{
|
||||||
lastWeightReadTime = currentMillis;
|
lastWeightReadTime = currentMillis;
|
||||||
|
|
||||||
// Prüfen ob die Waage korrekt genullt ist
|
// Prüfen ob die Waage korrekt genullt ist
|
||||||
if ((weight > 0 && weight < 5) || weight < 0)
|
if (autoTare && (weight > 0 && weight < 5) || weight < 0)
|
||||||
{
|
{
|
||||||
if(scaleTareCounter < 5)
|
scale_tare_counter++;
|
||||||
{
|
|
||||||
scaleTareCounter++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
scaleTareRequest = true;
|
|
||||||
scaleTareCounter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
scaleTareCounter = 0;
|
scale_tare_counter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prüfen ob das Gewicht gleich bleibt und dann senden
|
// Prüfen ob das Gewicht gleich bleibt und dann senden
|
||||||
@@ -183,15 +200,17 @@ void loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reset weight counter after writing tag
|
// reset weight counter after writing tag
|
||||||
if (currentMillis - lastWeightReadTime >= weightReadInterval && hasReadRfidTag > 1)
|
// TBD: what exactly is the logic behind this?
|
||||||
|
if (currentMillis - lastWeightReadTime >= weightReadInterval && nfcReaderState != NFC_IDLE && nfcReaderState != NFC_READ_SUCCESS)
|
||||||
{
|
{
|
||||||
weigthCouterToApi = 0;
|
weigthCouterToApi = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastWeight = weight;
|
lastWeight = weight;
|
||||||
|
|
||||||
// Wenn ein Tag mit SM id erkannte wurde und der Waage Counter anspricht an SM Senden
|
// Wenn ein Tag mit SM id erkannte wurde und der Waage Counter anspricht an SM Senden
|
||||||
if (spoolId != "" && weigthCouterToApi > 3 && weightSend == 0 && hasReadRfidTag == 1) {
|
if (spoolId != "" && weigthCouterToApi > 3 && weightSend == 0 && nfcReaderState == NFC_READ_SUCCESS)
|
||||||
|
{
|
||||||
oledShowIcon("loading");
|
oledShowIcon("loading");
|
||||||
if (updateSpoolWeight(spoolId, weight))
|
if (updateSpoolWeight(spoolId, weight))
|
||||||
{
|
{
|
||||||
@@ -211,6 +230,6 @@ void loop() {
|
|||||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
}
|
}
|
||||||
|
|||||||
+294
-120
@@ -7,9 +7,23 @@
|
|||||||
#include "api.h"
|
#include "api.h"
|
||||||
#include "esp_task_wdt.h"
|
#include "esp_task_wdt.h"
|
||||||
#include "scale.h"
|
#include "scale.h"
|
||||||
|
#include <SPI.h>
|
||||||
|
|
||||||
//Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS);
|
// Pin definitions for both PN532 chips
|
||||||
Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);
|
#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);
|
||||||
|
|
||||||
TaskHandle_t RfidReaderTask;
|
TaskHandle_t RfidReaderTask;
|
||||||
|
|
||||||
@@ -18,7 +32,7 @@ String spoolId = "";
|
|||||||
String nfcJsonData = "";
|
String nfcJsonData = "";
|
||||||
volatile bool pauseBambuMqttTask = false;
|
volatile bool pauseBambuMqttTask = false;
|
||||||
|
|
||||||
volatile uint8_t hasReadRfidTag = 0;
|
volatile nfcReaderStateType nfcReaderState = NFC_IDLE;
|
||||||
// 0 = nicht gelesen
|
// 0 = nicht gelesen
|
||||||
// 1 = erfolgreich gelesen
|
// 1 = erfolgreich gelesen
|
||||||
// 2 = fehler beim Lesen
|
// 2 = fehler beim Lesen
|
||||||
@@ -28,6 +42,165 @@ volatile uint8_t hasReadRfidTag = 0;
|
|||||||
// 6 = reading
|
// 6 = reading
|
||||||
// ***** PN532
|
// ***** 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 #####
|
// ##### Funktionen für RFID #####
|
||||||
void payloadToJson(uint8_t *data) {
|
void payloadToJson(uint8_t *data) {
|
||||||
@@ -80,7 +253,7 @@ bool formatNdefTag() {
|
|||||||
|
|
||||||
// Schreibe die Initialisierungsnachricht auf die ersten Seiten
|
// Schreibe die Initialisierungsnachricht auf die ersten Seiten
|
||||||
for (int i = 0; i < sizeof(ndefInit); i += 4) {
|
for (int i = 0; i < sizeof(ndefInit); i += 4) {
|
||||||
if (!nfc.ntag2xx_WritePage(pageOffset + (i / 4), &ndefInit[i])) {
|
if (!nfc1.ntag2xx_WritePage(pageOffset + (i / 4), &ndefInit[i])) {
|
||||||
success = false;
|
success = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -89,16 +262,15 @@ bool formatNdefTag() {
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t readTagSize()
|
uint16_t readTagSize(Adafruit_PN532 &pn532) {
|
||||||
{
|
uint8_t buffer[4];
|
||||||
uint8_t buffer[4];
|
memset(buffer, 0, 4);
|
||||||
memset(buffer, 0, 4);
|
pn532.ntag2xx_ReadPage(3, buffer);
|
||||||
nfc.ntag2xx_ReadPage(3, buffer);
|
return buffer[2] * 8;
|
||||||
return buffer[2]*8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ntag2xx_WriteNDEF(const char *payload) {
|
uint8_t ntag2xx_WriteNDEF(const char *payload, Adafruit_PN532 &pn532) {
|
||||||
uint16_t tagSize = readTagSize();
|
uint16_t tagSize = readTagSize(pn532);
|
||||||
Serial.print("Tag Size: ");Serial.println(tagSize);
|
Serial.print("Tag Size: ");Serial.println(tagSize);
|
||||||
|
|
||||||
uint8_t pageBuffer[4] = {0, 0, 0, 0};
|
uint8_t pageBuffer[4] = {0, 0, 0, 0};
|
||||||
@@ -157,11 +329,7 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) {
|
|||||||
int bytesToWrite = (totalSize < 4) ? totalSize : 4;
|
int bytesToWrite = (totalSize < 4) ? totalSize : 4;
|
||||||
memcpy(pageBuffer, combinedData + a, bytesToWrite);
|
memcpy(pageBuffer, combinedData + a, bytesToWrite);
|
||||||
|
|
||||||
//uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
|
if (!(pn532.ntag2xx_WritePage(4+i, pageBuffer)))
|
||||||
//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.");
|
Serial.println("Fehler beim Schreiben der Seite.");
|
||||||
free(combinedData);
|
free(combinedData);
|
||||||
@@ -169,8 +337,6 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
//esp_task_wdt_reset();
|
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
a += 4;
|
a += 4;
|
||||||
totalSize -= bytesToWrite;
|
totalSize -= bytesToWrite;
|
||||||
@@ -179,7 +345,7 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) {
|
|||||||
// Ensure the NDEF message is properly terminated
|
// Ensure the NDEF message is properly terminated
|
||||||
memset(pageBuffer, 0, 4);
|
memset(pageBuffer, 0, 4);
|
||||||
pageBuffer[0] = 0xFE; // NDEF record footer
|
pageBuffer[0] = 0xFE; // NDEF record footer
|
||||||
if (!(nfc.ntag2xx_WritePage(4+i, pageBuffer)))
|
if (!(pn532.ntag2xx_WritePage(4+i, pageBuffer)))
|
||||||
{
|
{
|
||||||
Serial.println("Fehler beim Schreiben des End-Bits.");
|
Serial.println("Fehler beim Schreiben des End-Bits.");
|
||||||
free(combinedData);
|
free(combinedData);
|
||||||
@@ -238,32 +404,43 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage) {
|
|||||||
void writeJsonToTag(void *parameter) {
|
void writeJsonToTag(void *parameter) {
|
||||||
const char* payload = (const char*)parameter;
|
const char* payload = (const char*)parameter;
|
||||||
|
|
||||||
// Gib die erstellte NDEF-Message aus
|
|
||||||
Serial.println("Erstelle NDEF-Message...");
|
Serial.println("Erstelle NDEF-Message...");
|
||||||
Serial.println(payload);
|
Serial.println(payload);
|
||||||
|
|
||||||
hasReadRfidTag = 3;
|
nfcReaderState = NFC_WRITING;
|
||||||
vTaskSuspend(RfidReaderTask);
|
vTaskSuspend(RfidReaderTask);
|
||||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
//pauseBambuMqttTask = true;
|
|
||||||
// aktualisieren der Website wenn sich der Status ändert
|
|
||||||
sendNfcData(nullptr);
|
sendNfcData(nullptr);
|
||||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||||
oledShowMessage("Waiting for NFC-Tag");
|
oledShowMessage("Waiting for NFC-Tag");
|
||||||
|
|
||||||
// Wait 10sec for tag
|
// Try both readers
|
||||||
uint8_t success = 0;
|
uint8_t success = 0;
|
||||||
String uidString = "";
|
String uidString = "";
|
||||||
|
Adafruit_PN532* activeReader = nullptr;
|
||||||
|
|
||||||
for (uint16_t i = 0; i < 20; i++) {
|
for (uint16_t i = 0; i < 20; i++) {
|
||||||
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
|
// Try first reader
|
||||||
|
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };
|
||||||
uint8_t uidLength;
|
uint8_t uidLength;
|
||||||
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 500);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
for (uint8_t i = 0; i < uidLength; i++) {
|
for (uint8_t i = 0; i < uidLength; i++) {
|
||||||
uidString += String(uid[i], HEX);
|
uidString += String(uid[i], HEX);
|
||||||
if (i < uidLength - 1) {
|
if (i < uidLength - 1) {
|
||||||
uidString += ":"; // Optional: Trennzeichen hinzufügen
|
uidString += ":";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foundNfcTag(nullptr, success);
|
foundNfcTag(nullptr, success);
|
||||||
@@ -277,50 +454,42 @@ void writeJsonToTag(void *parameter) {
|
|||||||
vTaskDelay(pdMS_TO_TICKS(1));
|
vTaskDelay(pdMS_TO_TICKS(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success)
|
if (success && activeReader != nullptr) {
|
||||||
{
|
|
||||||
oledShowIcon("transfer");
|
oledShowIcon("transfer");
|
||||||
// Schreibe die NDEF-Message auf den Tag
|
// Schreibe die NDEF-Message auf den Tag
|
||||||
success = ntag2xx_WriteNDEF(payload);
|
success = ntag2xx_WriteNDEF(payload, *activeReader);
|
||||||
if (success)
|
if (success) {
|
||||||
{
|
|
||||||
Serial.println("NDEF-Message erfolgreich auf den Tag geschrieben");
|
Serial.println("NDEF-Message erfolgreich auf den Tag geschrieben");
|
||||||
//oledShowMessage("NFC-Tag written");
|
|
||||||
oledShowIcon("success");
|
oledShowIcon("success");
|
||||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
hasReadRfidTag = 5;
|
nfcReaderState = NFC_WRITE_SUCCESS;
|
||||||
// aktualisieren der Website wenn sich der Status ändert
|
|
||||||
sendNfcData(nullptr);
|
sendNfcData(nullptr);
|
||||||
pauseBambuMqttTask = false;
|
pauseBambuMqttTask = false;
|
||||||
|
|
||||||
if (updateSpoolTagId(uidString, payload)) {
|
if (updateSpoolTagId(uidString, payload)) {
|
||||||
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
|
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };
|
||||||
uint8_t uidLength;
|
uint8_t uidLength;
|
||||||
oledShowIcon("success");
|
oledShowIcon("success");
|
||||||
while (nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 500)) {
|
while (activeReader->readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 500)) {
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vTaskResume(RfidReaderTask);
|
vTaskResume(RfidReaderTask);
|
||||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
Serial.println("Fehler beim Schreiben der NDEF-Message auf den Tag");
|
Serial.println("Fehler beim Schreiben der NDEF-Message auf den Tag");
|
||||||
oledShowIcon("failed");
|
oledShowIcon("failed");
|
||||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||||
hasReadRfidTag = 4;
|
nfcReaderState = NFC_WRITE_ERROR;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
Serial.println("Fehler: Kein Tag zu schreiben gefunden.");
|
Serial.println("Fehler: Kein Tag zu schreiben gefunden.");
|
||||||
oledShowMessage("No NFC-Tag found");
|
oledShowMessage("No NFC-Tag found");
|
||||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||||
hasReadRfidTag = 0;
|
nfcReaderState = NFC_IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
sendWriteResult(nullptr, success);
|
sendWriteResult(nullptr, success);
|
||||||
sendNfcData(nullptr);
|
sendNfcData(nullptr);
|
||||||
|
|
||||||
@@ -334,7 +503,7 @@ void startWriteJsonToTag(const char* payload) {
|
|||||||
char* payloadCopy = strdup(payload);
|
char* payloadCopy = strdup(payload);
|
||||||
|
|
||||||
// Task nicht mehrfach starten
|
// Task nicht mehrfach starten
|
||||||
if (hasReadRfidTag != 3) {
|
if (nfcReaderState != NFC_WRITING) {
|
||||||
// Erstelle die Task
|
// Erstelle die Task
|
||||||
xTaskCreate(
|
xTaskCreate(
|
||||||
writeJsonToTag, // Task-Funktion
|
writeJsonToTag, // Task-Funktion
|
||||||
@@ -348,69 +517,79 @@ void startWriteJsonToTag(const char* payload) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void scanRfidTask(void * parameter) {
|
void scanRfidTask(void * parameter) {
|
||||||
Serial.println("RFID Task gestartet");
|
Serial.println("RFID Task gestartet");
|
||||||
for(;;) {
|
if (nfcReaderState != NFC_WRITING)
|
||||||
// Wenn geschrieben wird Schleife aussetzen
|
|
||||||
if (hasReadRfidTag != 3)
|
|
||||||
{
|
{
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
uint8_t success;
|
uint8_t success = 0;
|
||||||
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
|
uint8_t uid[] = {0, 0, 0, 0, 0, 0, 0};
|
||||||
uint8_t uidLength;
|
uint8_t uidLength;
|
||||||
|
Adafruit_PN532 *activeReader = nullptr;
|
||||||
|
|
||||||
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 1000);
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foundNfcTag(nullptr, success);
|
foundNfcTag(nullptr, success);
|
||||||
|
|
||||||
if (success && hasReadRfidTag != 1)
|
if (success && nfcReaderState != NFC_READ_SUCCESS && activeReader != nullptr)
|
||||||
{
|
{
|
||||||
// Display some basic information about the card
|
|
||||||
Serial.println("Found an ISO14443A card");
|
Serial.println("Found an ISO14443A card");
|
||||||
|
|
||||||
hasReadRfidTag = 6;
|
nfcReaderState = NFC_READING;
|
||||||
|
|
||||||
oledShowIcon("transfer");
|
oledShowIcon("transfer");
|
||||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
if (uidLength == 7)
|
if (uidLength == 7)
|
||||||
{
|
{
|
||||||
uint16_t tagSize = readTagSize();
|
uint16_t tagSize = readTagSize(*activeReader);
|
||||||
if(tagSize > 0)
|
if (tagSize > 0)
|
||||||
{
|
{
|
||||||
// Create a buffer depending on the size of the tag
|
uint8_t *data = (uint8_t *)malloc(tagSize);
|
||||||
uint8_t* data = (uint8_t*)malloc(tagSize);
|
|
||||||
memset(data, 0, 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)");
|
Serial.println("Seems to be an NTAG2xx tag (7 byte UID)");
|
||||||
|
|
||||||
uint8_t numPages = readTagSize()/4;
|
uint8_t numPages = readTagSize(*activeReader) / 4;
|
||||||
for (uint8_t i = 4; i < 4+numPages; i++) {
|
for (uint8_t i = 4; i < 4 + numPages; i++)
|
||||||
if (!nfc.ntag2xx_ReadPage(i, data+(i-4) * 4))
|
{
|
||||||
|
if (!activeReader->ntag2xx_ReadPage(i, data + (i - 4) * 4))
|
||||||
{
|
{
|
||||||
break; // Stop if reading fails
|
break;
|
||||||
}
|
}
|
||||||
// Check for NDEF message end
|
if (data[(i - 4) * 4] == 0xFE)
|
||||||
if (data[(i - 4) * 4] == 0xFE)
|
|
||||||
{
|
{
|
||||||
break; // End of NDEF message
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
vTaskDelay(pdMS_TO_TICKS(1));
|
vTaskDelay(pdMS_TO_TICKS(5)); // Increased delay between page reads
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!decodeNdefAndReturnJson(data))
|
if (!decodeNdefAndReturnJson(data))
|
||||||
{
|
{
|
||||||
oledShowMessage("NFC-Tag unknown");
|
oledShowMessage("NFC-Tag unknown");
|
||||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||||
hasReadRfidTag = 2;
|
nfcReaderState = NFC_READ_ERROR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hasReadRfidTag = 1;
|
nfcReaderState = NFC_READ_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(data);
|
free(data);
|
||||||
@@ -418,7 +597,7 @@ void scanRfidTask(void * parameter) {
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
oledShowMessage("NFC-Tag read error");
|
oledShowMessage("NFC-Tag read error");
|
||||||
hasReadRfidTag = 2;
|
nfcReaderState = NFC_READ_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -427,58 +606,53 @@ void scanRfidTask(void * parameter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success && hasReadRfidTag > 0)
|
if (!success && nfcReaderState != NFC_IDLE)
|
||||||
{
|
{
|
||||||
hasReadRfidTag = 0;
|
nfcReaderState = NFC_IDLE;
|
||||||
//uidString = "";
|
|
||||||
nfcJsonData = "";
|
nfcJsonData = "";
|
||||||
Serial.println("Tag entfernt");
|
Serial.println("Tag entfernt");
|
||||||
if (!autoSendToBambu) oledShowWeight(weight);
|
if (!autoSendToBambu)
|
||||||
|
oledShowWeight(weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
// aktualisieren der Website wenn sich der Status ändert
|
|
||||||
sendNfcData(nullptr);
|
sendNfcData(nullptr);
|
||||||
|
delay(100); // Add small delay at end of loop
|
||||||
}
|
}
|
||||||
yield();
|
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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void startNfc() {
|
String createTagId(uint8_t *uid, uint8_t uidLength)
|
||||||
nfc.begin(); // Beginne Kommunikation mit RFID Leser
|
{
|
||||||
delay(1000);
|
String tagId = ""; // Initialisieren Sie einen leeren String
|
||||||
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); //
|
|
||||||
|
|
||||||
nfc.SAMConfig();
|
// Erstellen Sie die Tag-ID basierend auf dem UID
|
||||||
// Set the max number of retry attempts to read from a card
|
for (uint8_t i = 0; i < uidLength; i++)
|
||||||
// This prevents us from waiting forever for a card, which is
|
{
|
||||||
// the default behaviour of the PN532.
|
tagId += String(uid[i], HEX); // Konvertieren Sie die UID in einen String
|
||||||
//nfc.setPassiveActivationRetries(0x7F);
|
if (i < uidLength - 1)
|
||||||
//nfc.setPassiveActivationRetries(0xFF);
|
{
|
||||||
|
tagId += ":"; // Fügen Sie einen Trennstrich hinzu, wenn es nicht das letzte Element ist
|
||||||
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);
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,32 @@
|
|||||||
#ifndef NFC_H
|
#pragma once
|
||||||
#define NFC_H
|
|
||||||
|
|
||||||
#include <Arduino.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 startNfc();
|
||||||
void scanRfidTask(void * parameter);
|
|
||||||
void startWriteJsonToTag(const char* payload);
|
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);
|
||||||
|
|
||||||
extern TaskHandle_t RfidReaderTask;
|
extern TaskHandle_t RfidReaderTask;
|
||||||
extern String nfcJsonData;
|
extern String nfcJsonData;
|
||||||
extern String spoolId;
|
extern String spoolId;
|
||||||
extern volatile uint8_t hasReadRfidTag;
|
extern volatile nfcReaderStateType nfcReaderState;
|
||||||
extern volatile bool pauseBambuMqttTask;
|
extern volatile bool pauseBambuMqttTask;
|
||||||
|
|
||||||
#endif
|
// Function declarations
|
||||||
|
uint16_t readTagSize(Adafruit_PN532 &pn532);
|
||||||
|
String createTagId(uint8_t *uid, uint8_t uidLength);
|
||||||
+42
-4
@@ -14,6 +14,7 @@ TaskHandle_t ScaleTask;
|
|||||||
int16_t weight = 0;
|
int16_t weight = 0;
|
||||||
|
|
||||||
uint8_t weigthCouterToApi = 0;
|
uint8_t weigthCouterToApi = 0;
|
||||||
|
uint8_t scale_tare_counter = 0;
|
||||||
bool scaleTareRequest = false;
|
bool scaleTareRequest = false;
|
||||||
uint8_t pauseMainTask = 0;
|
uint8_t pauseMainTask = 0;
|
||||||
uint8_t scaleCalibrated = 1;
|
uint8_t scaleCalibrated = 1;
|
||||||
@@ -21,9 +22,26 @@ uint8_t scaleCalibrated = 1;
|
|||||||
Preferences preferences;
|
Preferences preferences;
|
||||||
const char* NVS_NAMESPACE = "scale";
|
const char* NVS_NAMESPACE = "scale";
|
||||||
const char* NVS_KEY_CALIBRATION = "cal_value";
|
const char* NVS_KEY_CALIBRATION = "cal_value";
|
||||||
|
const char *NVS_KEY_AUTOTARE = "auto_tare";
|
||||||
|
bool autoTare = true;
|
||||||
|
|
||||||
// ##### Funktionen für Waage #####
|
// ##### Funktionen für Waage #####
|
||||||
uint8_t tareScale() {
|
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()
|
||||||
|
{
|
||||||
Serial.println("Tare scale");
|
Serial.println("Tare scale");
|
||||||
scale.tare();
|
scale.tare();
|
||||||
|
|
||||||
@@ -38,11 +56,23 @@ void scale_loop(void * parameter) {
|
|||||||
for(;;) {
|
for(;;) {
|
||||||
if (scale.is_ready())
|
if (scale.is_ready())
|
||||||
{
|
{
|
||||||
// Waage nochmal Taren, wenn zu lange Abweichung
|
// Waage automatisch Taren, wenn zu lange Abweichung
|
||||||
if (scaleTareRequest == true)
|
if (autoTare && scale_tare_counter >= 5)
|
||||||
|
{
|
||||||
|
Serial.println("Auto Tare scale");
|
||||||
|
scale.tare();
|
||||||
|
scale_tare_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Waage manuell Taren
|
||||||
|
if (scaleTareRequest == true)
|
||||||
{
|
{
|
||||||
Serial.println("Re-Tare scale");
|
Serial.println("Re-Tare scale");
|
||||||
|
oledShowMessage("TARE Scale");
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
scale.tare();
|
scale.tare();
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
oledShowWeight(0);
|
||||||
scaleTareRequest = false;
|
scaleTareRequest = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,13 +83,21 @@ void scale_loop(void * parameter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_scale() {
|
void start_scale(bool touchSensorConnected)
|
||||||
|
{
|
||||||
Serial.println("Prüfe Calibration Value");
|
Serial.println("Prüfe Calibration Value");
|
||||||
float calibrationValue;
|
float calibrationValue;
|
||||||
|
|
||||||
// NVS lesen
|
// NVS lesen
|
||||||
preferences.begin(NVS_NAMESPACE, true); // true = readonly
|
preferences.begin(NVS_NAMESPACE, true); // true = readonly
|
||||||
calibrationValue = preferences.getFloat(NVS_KEY_CALIBRATION, defaultScaleCalibrationValue);
|
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();
|
preferences.end();
|
||||||
|
|
||||||
Serial.print("Read Scale Calibration Value ");
|
Serial.print("Read Scale Calibration Value ");
|
||||||
|
|||||||
+4
-2
@@ -4,17 +4,19 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "HX711.h"
|
#include "HX711.h"
|
||||||
|
|
||||||
|
uint8_t setAutoTare(bool autoTareValue);
|
||||||
uint8_t start_scale();
|
uint8_t start_scale(bool touchSensorConnected);
|
||||||
uint8_t calibrate_scale();
|
uint8_t calibrate_scale();
|
||||||
uint8_t tareScale();
|
uint8_t tareScale();
|
||||||
|
|
||||||
extern HX711 scale;
|
extern HX711 scale;
|
||||||
extern int16_t weight;
|
extern int16_t weight;
|
||||||
extern uint8_t weigthCouterToApi;
|
extern uint8_t weigthCouterToApi;
|
||||||
|
extern uint8_t scale_tare_counter;
|
||||||
extern uint8_t scaleTareRequest;
|
extern uint8_t scaleTareRequest;
|
||||||
extern uint8_t pauseMainTask;
|
extern uint8_t pauseMainTask;
|
||||||
extern uint8_t scaleCalibrated;
|
extern uint8_t scaleCalibrated;
|
||||||
|
extern bool autoTare;
|
||||||
|
|
||||||
extern TaskHandle_t ScaleTask;
|
extern TaskHandle_t ScaleTask;
|
||||||
|
|
||||||
|
|||||||
+66
-37
@@ -22,14 +22,13 @@ AsyncWebServer server(webserverPort);
|
|||||||
AsyncWebSocket ws("/ws");
|
AsyncWebSocket ws("/ws");
|
||||||
|
|
||||||
uint8_t lastSuccess = 0;
|
uint8_t lastSuccess = 0;
|
||||||
uint8_t lastHasReadRfidTag = 0;
|
nfcReaderStateType lastnfcReaderState = NFC_IDLE;
|
||||||
|
|
||||||
|
|
||||||
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
|
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
|
||||||
if (type == WS_EVT_CONNECT) {
|
if (type == WS_EVT_CONNECT) {
|
||||||
Serial.println("Neuer Client verbunden!");
|
Serial.println("Neuer Client verbunden!");
|
||||||
// Sende die AMS-Daten an den neuen Client
|
// Sende die AMS-Daten an den neuen Client
|
||||||
sendAmsData(client);
|
if (!bambuDisabled) sendAmsData(client);
|
||||||
sendNfcData(client);
|
sendNfcData(client);
|
||||||
foundNfcTag(client, 0);
|
foundNfcTag(client, 0);
|
||||||
sendWriteResult(client, 3);
|
sendWriteResult(client, 3);
|
||||||
@@ -43,6 +42,7 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
|
|||||||
String message = String((char*)data);
|
String message = String((char*)data);
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
deserializeJson(doc, message);
|
deserializeJson(doc, message);
|
||||||
|
bool spoolmanConnected = (spoolmanApiState != API_INIT);
|
||||||
|
|
||||||
if (doc["type"] == "heartbeat") {
|
if (doc["type"] == "heartbeat") {
|
||||||
// Sende Heartbeat-Antwort
|
// Sende Heartbeat-Antwort
|
||||||
@@ -50,7 +50,7 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
|
|||||||
"\"type\":\"heartbeat\","
|
"\"type\":\"heartbeat\","
|
||||||
"\"freeHeap\":" + String(ESP.getFreeHeap()/1024) + ","
|
"\"freeHeap\":" + String(ESP.getFreeHeap()/1024) + ","
|
||||||
"\"bambu_connected\":" + String(bambu_connected) + ","
|
"\"bambu_connected\":" + String(bambu_connected) + ","
|
||||||
"\"spoolman_connected\":" + String(spoolman_connected) + ""
|
"\"spoolman_connected\":" + String(spoolmanConnected) + ""
|
||||||
"}");
|
"}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,6 +73,11 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
|
|||||||
success = calibrate_scale();
|
success = calibrate_scale();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (doc["payload"] == "setAutoTare")
|
||||||
|
{
|
||||||
|
success = setAutoTare(doc["enabled"].as<bool>());
|
||||||
|
}
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
ws.textAll("{\"type\":\"scale\",\"payload\":\"success\"}");
|
ws.textAll("{\"type\":\"scale\",\"payload\":\"success\"}");
|
||||||
} else {
|
} else {
|
||||||
@@ -139,34 +144,33 @@ void foundNfcTag(AsyncWebSocketClient *client, uint8_t success) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sendNfcData(AsyncWebSocketClient *client) {
|
void sendNfcData(AsyncWebSocketClient *client) {
|
||||||
if (lastHasReadRfidTag == hasReadRfidTag) return;
|
if (lastnfcReaderState == nfcReaderState)
|
||||||
if (hasReadRfidTag == 0) {
|
return;
|
||||||
|
// TBD: Why is there no status for reading the tag?
|
||||||
|
switch (nfcReaderState)
|
||||||
|
{
|
||||||
|
case NFC_IDLE:
|
||||||
ws.textAll("{\"type\":\"nfcData\", \"payload\":{}}");
|
ws.textAll("{\"type\":\"nfcData\", \"payload\":{}}");
|
||||||
}
|
break;
|
||||||
else if (hasReadRfidTag == 1) {
|
case NFC_READ_SUCCESS:
|
||||||
ws.textAll("{\"type\":\"nfcData\", \"payload\":" + nfcJsonData + "}");
|
ws.textAll("{\"type\":\"nfcData\", \"payload\":" + nfcJsonData + "}");
|
||||||
}
|
break;
|
||||||
else if (hasReadRfidTag == 2)
|
case NFC_READ_ERROR:
|
||||||
{
|
|
||||||
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Empty Tag or Data not readable\"}}");
|
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Empty Tag or Data not readable\"}}");
|
||||||
}
|
break;
|
||||||
else if (hasReadRfidTag == 3)
|
case NFC_WRITING:
|
||||||
{
|
|
||||||
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Schreibe Tag...\"}}");
|
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Schreibe Tag...\"}}");
|
||||||
}
|
break;
|
||||||
else if (hasReadRfidTag == 4)
|
case NFC_WRITE_SUCCESS:
|
||||||
{
|
|
||||||
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Error writing to Tag\"}}");
|
|
||||||
}
|
|
||||||
else if (hasReadRfidTag == 5)
|
|
||||||
{
|
|
||||||
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Tag erfolgreich geschrieben\"}}");
|
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Tag erfolgreich geschrieben\"}}");
|
||||||
}
|
break;
|
||||||
else
|
case NFC_WRITE_ERROR:
|
||||||
{
|
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Error writing to Tag\"}}");
|
||||||
|
break;
|
||||||
|
case DEFAULT:
|
||||||
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Something went wrong\"}}");
|
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Something went wrong\"}}");
|
||||||
}
|
}
|
||||||
lastHasReadRfidTag = hasReadRfidTag;
|
lastnfcReaderState = nfcReaderState;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendAmsData(AsyncWebSocketClient *client) {
|
void sendAmsData(AsyncWebSocketClient *client) {
|
||||||
@@ -202,18 +206,24 @@ void setupWebserver(AsyncWebServer &server) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Route für Waage
|
// 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");
|
Serial.println("Anfrage für /waage erhalten");
|
||||||
AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/waage.html.gz", "text/html");
|
//AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/waage.html.gz", "text/html");
|
||||||
response->addHeader("Content-Encoding", "gzip");
|
//response->addHeader("Content-Encoding", "gzip");
|
||||||
response->addHeader("Cache-Control", CACHE_CONTROL);
|
//response->addHeader("Cache-Control", CACHE_CONTROL);
|
||||||
request->send(response);
|
|
||||||
});
|
String html = loadHtmlWithHeader("/waage.html");
|
||||||
|
html.replace("{{autoTare}}", (autoTare) ? "checked" : "");
|
||||||
|
|
||||||
|
request->send(200, "text/html", html); });
|
||||||
|
|
||||||
// Route für RFID
|
// Route für RFID
|
||||||
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
Serial.println("Anfrage für /rfid erhalten");
|
Serial.println("Anfrage für /rfid erhalten");
|
||||||
AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/rfid.html.gz", "text/html");
|
|
||||||
|
String page = (bambuDisabled) ? "/rfid.html.gz" : "/rfid_bambu.html.gz";
|
||||||
|
AsyncWebServerResponse *response = request->beginResponse(LittleFS, page, "text/html");
|
||||||
response->addHeader("Content-Encoding", "gzip");
|
response->addHeader("Content-Encoding", "gzip");
|
||||||
response->addHeader("Cache-Control", CACHE_CONTROL);
|
response->addHeader("Cache-Control", CACHE_CONTROL);
|
||||||
request->send(response);
|
request->send(response);
|
||||||
@@ -286,6 +296,16 @@ void setupWebserver(AsyncWebServer &server) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String url = request->getParam("url")->value();
|
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;
|
bool octoEnabled = (request->getParam("octoEnabled")->value() == "true") ? true : false;
|
||||||
String octoUrl = request->getParam("octoUrl")->value();
|
String octoUrl = request->getParam("octoUrl")->value();
|
||||||
String octoToken = (request->getParam("octoToken")->value() != "") ? request->getParam("octoToken")->value() : "";
|
String octoToken = (request->getParam("octoToken")->value() != "") ? request->getParam("octoToken")->value() : "";
|
||||||
@@ -300,8 +320,18 @@ void setupWebserver(AsyncWebServer &server) {
|
|||||||
request->send(200, "application/json", jsonResponse);
|
request->send(200, "application/json", jsonResponse);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route für das Überprüfen der Spoolman-Instanz
|
// Route für das Überprüfen der Bambu-Instanz
|
||||||
server.on("/api/bambu", HTTP_GET, [](AsyncWebServerRequest *request){
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
if (!request->hasParam("bambu_ip") || !request->hasParam("bambu_serialnr") || !request->hasParam("bambu_accesscode")) {
|
if (!request->hasParam("bambu_ip") || !request->hasParam("bambu_serialnr") || !request->hasParam("bambu_accesscode")) {
|
||||||
request->send(400, "application/json", "{\"success\": false, \"error\": \"Missing parameter\"}");
|
request->send(400, "application/json", "{\"success\": false, \"error\": \"Missing parameter\"}");
|
||||||
return;
|
return;
|
||||||
@@ -325,8 +355,7 @@ void setupWebserver(AsyncWebServer &server) {
|
|||||||
|
|
||||||
bool success = saveBambuCredentials(bambu_ip, bambu_serialnr, bambu_accesscode, autoSend, autoSendTime);
|
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
|
// Route für das Überprüfen der Spoolman-Instanz
|
||||||
server.on("/reboot", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/reboot", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@ void initWiFi() {
|
|||||||
if(wm_nonblocking) wm.setConfigPortalBlocking(false);
|
if(wm_nonblocking) wm.setConfigPortalBlocking(false);
|
||||||
//wm.setConfigPortalTimeout(320); // Portal nach 5min schließen
|
//wm.setConfigPortalTimeout(320); // Portal nach 5min schließen
|
||||||
wm.setWiFiAutoReconnect(true);
|
wm.setWiFiAutoReconnect(true);
|
||||||
wm.setConnectTimeout(5);
|
wm.setConnectTimeout(10);
|
||||||
|
|
||||||
oledShowTopRow();
|
oledShowTopRow();
|
||||||
oledShowMessage("WiFi Setup");
|
oledShowMessage("WiFi Setup");
|
||||||
|
|||||||
Reference in New Issue
Block a user