Compare commits

..

22 Commits

Author SHA1 Message Date
tugsi 4dee298b73 Added
add auto-tare functionality and update scale handling based on touch sensor connection
2025-03-30 16:29:20 +02:00
tugsi c430c989ef Fixed
update touch sensor connection logic to correctly identify connection status
2025-03-30 15:17:47 +02:00
tugsi b40a2166f2 Fixed
enhance HTTP method handling in sendToApi function
2025-03-30 14:34:54 +02:00
tugsi 3590187cbe Added
Fixed
improve HTTP client configuration and clear update documents after API calls (Manuel Weiser)
6cc4efc - Fixes memory leak in HTTPClient by disabling connection reuse (Jan Philipp Ecker)
update reload logic after removing and saving Bambu credentials for better cache handling (Manuel Weiser)
Changed
docs: update changelog and header for version v1.4.8 (Manuel Weiser)
docs: update platformio.ini for version v1.4.8 (Manuel Weiser)
Merge pull request #30 from janecker/main (ManuelW)
Merge branch 'testing' into main (ManuelW)
2025-03-30 14:32:11 +02:00
tugsi 0302725bc7 Added
add forced cache refresh after removing and saving Bambu credentials (Manuel Weiser)
add functionality to remove Bambu credentials and update API handling (Manuel Weiser)
add rfid_bambu.html and update bambu connection handling (Manuel Weiser)
Fixed
handle Bambu connection state by introducing bambuDisabled flag (Manuel Weiser)
fe4d2d7 - Fix rfid.js-Failure with X1-Series, if you wanna send a Spool to AMS: - Uncaught TypeError: Cannot read properties of undefined (reading 'replace') at handleSpoolIn (rfid.js:493:67) at HTMLButtonElement.onclick ((Index):1:1) handleSpoolIn @ rfid.js:493 onclick @ (Index):1 (tugsi)
Changed
docs: update changelog and header for version v1.4.7 (Manuel Weiser)
docs: update platformio.ini for version v1.4.7 (Manuel Weiser)
Merge branch 'testing' (Manuel Weiser)
style: update remove button for Bambu credentials with red background (Manuel Weiser)
Merge pull request #28 from tugsi/main (ManuelW)
2025-03-30 14:28:17 +02:00
tugsi 75fbd5ebc3 Version-Fix - get it´s own Version 2025-03-24 18:21:41 +01:00
tugsi 53894a3746 Changed RFID to SPI and for using 2 PN532 2025-03-24 17:32:57 +01:00
tugsi 360c925cfc More Diag-Infos Heap-memory 2025-03-24 17:09:19 +01:00
tugsi fc5d77c97b fix: adjust weight threshold for tare check to allow negative values 2025-03-24 16:54:36 +01:00
tugsi f869bcc0c1 Origin Rfid.js 2025-03-23 18:58:33 +01:00
tugsi b75be0ac06 fix 2025-03-23 18:53:57 +01:00
tugsi 1c01bfb2da - X1C MQTT Fix
- Spoolman Settings Fix
- Spoolman Out Fix
- Spoolman In Fix
2025-03-23 18:09:25 +01:00
tugsi 15d0bfd8e9 gitgnore 2025-03-23 17:43:10 +01:00
tugsi d363a7b905 fix: add error handling for missing vendor IDs in filament data 2025-03-23 17:14:53 +01:00
tugsi 9d7accc746 fix: use unique client ID for MQTT connection to avoid conflicts 2025-03-23 16:42:52 +01:00
tugsi c2e3dc1d46 fix: reload page after firmware update completion 2025-03-23 16:35:03 +01:00
tugsi d81cf5d4e4 fix: ensure valid URL format and remove trailing slash in setupWebserver 2025-03-23 16:33:02 +01:00
tugsi 75e13387c8 fix: add WiFi connection check and restart Bambu if not connected 2025-03-23 16:31:12 +01:00
tugsi 6534419381 increase stack size for BambuMqtt task 2025-03-23 16:27:20 +01:00
tugsi e55b2d7fdf Merge pull request '- WifiTimeout changed from 5s to 10s #Issue22' (#1) from WLAN-Timeout into main
Reviewed-on: http://10.10.10.101:3000/tugsi/Filaman_V2/pulls/1
2025-03-23 16:00:37 +01:00
tugsi 4aa81c7842 - WifiTimeout changed from 5s to 10s #Issue22 2025-03-21 08:00:59 +01:00
tugsi 8ff4e81826 Merge branch 'ManuelW77:main' into main 2025-03-16 19:50:13 +01:00
27 changed files with 616 additions and 234 deletions
-4
View File
@@ -1,7 +1,3 @@
.pio
.vscode
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
data
-10
View File
@@ -1,10 +0,0 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}
-9
View File
@@ -141,15 +141,6 @@
</div>
</div>
<!-- Rechte Spalte -->
<div class="column">
<div class="feature-box">
<h2>Bambu AMS</h2>
<div id="amsDataContainer">
<div class="amsData" id="amsData">Wait for AMS-Data...</div>
</div>
</div>
</div>
</div>
</div>
+1 -2
View File
@@ -685,5 +685,4 @@ function showNotification(message, isSuccess) {
setTimeout(() => {
notification.remove();
}, 300);
}, 3000);
}
}, 3000);}
+165
View File
@@ -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>
+31
View File
@@ -57,6 +57,31 @@
toggleOctoFields();
};
function removeBambuCredentials() {
fetch('/api/bambu?remove=true')
.then(response => response.json())
.then(data => {
if (data.success) {
document.getElementById('bambuIp').value = '';
document.getElementById('bambuSerial').value = '';
document.getElementById('bambuCode').value = '';
document.getElementById('autoSend').checked = false;
document.getElementById('autoSendTime').value = '';
document.getElementById('bambuStatusMessage').innerText = 'Bambu Credentials removed!';
// Reload with forced cache refresh after short delay
setTimeout(() => {
window.location.reload(true);
window.location.href = '/';
}, 1500);
} else {
document.getElementById('bambuStatusMessage').innerText = 'Error while removing Bambu Credentials.';
}
})
.catch(error => {
document.getElementById('bambuStatusMessage').innerText = 'Error while removing: ' + error.message;
});
}
function checkSpoolmanInstance() {
const url = document.getElementById('spoolmanUrl').value;
const spoolmanOctoEnabled = document.getElementById('spoolmanOctoEnabled').checked;
@@ -89,6 +114,11 @@
.then(data => {
if (data.healthy) {
document.getElementById('bambuStatusMessage').innerText = 'Bambu Credentials saved!';
// Reload with forced cache refresh after short delay
setTimeout(() => {
window.location.reload(true);
window.location.href = '/';
}, 1500);
} else {
document.getElementById('bambuStatusMessage').innerText = 'Error while saving Bambu Credentials.';
}
@@ -162,6 +192,7 @@
</div>
<button style="margin: 0;" onclick="saveBambuCredentials()">Save Bambu Credentials</button>
<button style="margin: 0; background-color: red;" onclick="removeBambuCredentials()">Remove Credentials</button>
<p id="bambuStatusMessage"></p>
</div>
</div>
+7 -12
View File
@@ -147,6 +147,13 @@ function updateFilamentDropdown(selectedSmId = null) {
if (vendorId) {
const filteredFilaments = spoolsData.filter(spool => {
if (!spool?.filament?.vendor?.id) {
console.log('Problem aufgetreten bei: ', spool?.filament?.vendor);
console.log('Problematische Spulen:',
spoolsData.filter(spool => !spool?.filament?.vendor?.id));
return false;
}
const hasValidNfcId = spool.extra &&
spool.extra.nfc_id &&
spool.extra.nfc_id !== '""' &&
@@ -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
document.addEventListener('DOMContentLoaded', () => {
initSpoolman();
+2
View File
@@ -129,6 +129,7 @@
if (data.status === 'success' || lastReceivedProgress >= 98) {
clearTimeout(wsReconnectTimer);
setTimeout(() => {
window.location.reload(true);
window.location.href = '/';
}, 30000);
}
@@ -164,6 +165,7 @@
status.className = 'status success';
status.style.display = 'block';
setTimeout(() => {
window.location.reload(true);
window.location.href = '/';
}, 30000);
}
+10
View File
@@ -55,6 +55,8 @@
<h5 class="card-title">Sacle Calibration</h5>
<button id="calibrateBtn" class="btn btn-primary">Calibrate Scale</button>
<button id="tareBtn" class="btn btn-secondary">Tare Scale</button>
&nbsp;&nbsp;&nbsp;Enable Auto-TARE <input type="checkbox" id="autoTareCheckbox" onchange="setAutoTare(this.checked);"
{{autoTare}}>
<div id="statusMessage" class="mt-3"></div>
</div>
</div>
@@ -139,6 +141,14 @@
payload: 'tare'
}));
});
// Add auto-tare function
function setAutoTare(enabled) {
ws.send(JSON.stringify({
type: 'scale',
payload: 'setAutoTare',
enabled: enabled
}));
}
// WebSocket-Verbindung beim Laden der Seite initiieren
connectWebSocket();
+2 -2
View File
@@ -9,8 +9,8 @@
; https://docs.platformio.org/page/projectconf.html
[common]
version = "1.4.1"
to_old_version = "1.4.0"
version = "0.2.1"
to_old_version = "0.2.0"
##
[env:esp32dev]
+1 -1
View File
@@ -14,7 +14,7 @@ def copy_file(input_file, output_file):
def should_compress(file):
# Skip compression for spoolman.html
if file == 'spoolman.html':
if file == 'spoolman.html' or file == 'waage.html':
return False
# Komprimiere nur bestimmte Dateitypen
return file.endswith(('.js', '.png', '.css', '.html'))
+16 -5
View File
@@ -3,7 +3,7 @@
#include <ArduinoJson.h>
#include "commonFS.h"
bool spoolman_connected = false;
volatile spoolmanApiStateType spoolmanApiState = API_INIT;
String spoolmanUrl = "";
bool octoEnabled = false;
String octoUrl = "";
@@ -85,7 +85,8 @@ JsonDocument fetchSingleSpoolInfo(int spoolId) {
}
void sendToApi(void *parameter) {
SendToApiParams* params = (SendToApiParams*)parameter;
spoolmanApiState = API_TRANSMITTING;
SendToApiParams *params = (SendToApiParams *)parameter;
// Extrahiere die Werte
String httpType = params->httpType;
@@ -94,13 +95,17 @@ void sendToApi(void *parameter) {
String octoToken = params->octoToken;
HTTPClient http;
http.setReuse(false);
http.begin(spoolsUrl);
http.addHeader("Content-Type", "application/json");
if (octoEnabled && octoToken != "") http.addHeader("X-Api-Key", octoToken);
int httpCode = http.PUT(updatePayload);
int httpCode;
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) {
Serial.println("Spoolman erfolgreich aktualisiert");
@@ -111,10 +116,12 @@ void sendToApi(void *parameter) {
}
http.end();
vTaskDelay(50 / portTICK_PERIOD_MS);
// Speicher freigeben
delete params;
vTaskDelete(NULL);
spoolmanApiState = API_IDLE;
}
bool updateSpoolTagId(String uidString, const char* payload) {
@@ -164,6 +171,7 @@ bool updateSpoolTagId(String uidString, const char* payload) {
0, // Priorität
NULL // Task-Handle (nicht benötigt)
);
updateDoc.clear();
return true;
}
@@ -200,6 +208,7 @@ uint8_t updateSpoolWeight(String spoolId, uint16_t weight) {
0, // Priorität
NULL // Task-Handle (nicht benötigt)
);
updateDoc.clear();
return 1;
}
@@ -237,6 +246,7 @@ bool updateSpoolOcto(int spoolId) {
0, // Priorität
NULL // Task-Handle (nicht benötigt)
);
updateDoc.clear();
return true;
}
@@ -469,7 +479,8 @@ bool checkSpoolmanInstance(const String& url) {
return false;
}
spoolman_connected = true;
spoolmanApiState = API_IDLE;
oledShowTopRow();
return strcmp(status, "healthy") == 0;
}
}
+7
View File
@@ -6,7 +6,14 @@
#include "website.h"
#include "display.h"
#include <ArduinoJson.h>
typedef enum
{
API_INIT,
API_IDLE,
API_TRANSMITTING
} spoolmanApiStateType;
extern volatile spoolmanApiStateType spoolmanApiState;
extern bool spoolman_connected;
extern String spoolmanUrl;
extern bool octoEnabled;
+42 -10
View File
@@ -27,6 +27,7 @@ const char* bambu_serialnr = nullptr;
String g_bambu_ip = "";
String g_bambu_accesscode = "";
String g_bambu_serialnr = "";
bool bambuDisabled = false;
bool bambu_connected = false;
bool autoSendToBambu = false;
@@ -37,6 +38,35 @@ int ams_count = 0;
String amsJsonData; // Speichert das fertige JSON für WebSocket-Clients
AMSData ams_data[MAX_AMS]; // Definition des Arrays;
bool removeBambuCredentials()
{
if (BambuMqttTask)
{
vTaskDelete(BambuMqttTask);
}
if (!removeJsonValue("/bambu_credentials.json"))
{
Serial.println("Fehler beim Löschen der Bambu-Credentials.");
return false;
}
// Löschen der globalen Variablen
g_bambu_ip = "";
g_bambu_accesscode = "";
g_bambu_serialnr = "";
bambu_ip = nullptr;
bambu_accesscode = nullptr;
bambu_serialnr = nullptr;
autoSendToBambu = false;
autoSetToBambuSpoolId = 0;
ams_count = 0;
amsJsonData = "";
bambuDisabled = true;
return true;
}
bool saveBambuCredentials(const String& ip, const String& serialnr, const String& accesscode, bool autoSend, const String& autoSendTime) {
if (BambuMqttTask) {
vTaskDelete(BambuMqttTask);
@@ -266,8 +296,10 @@ bool setBambuSpool(String payload) {
JsonDocument doc;
DeserializationError error = deserializeJson(doc, payload);
if (error) {
Serial.print("Error parsing JSON: ");
Serial.print("Error parsing setBambuSpool-JSON: ");
Serial.println(error.c_str());
Serial.print("Free Heap-Memory: ");
Serial.println(ESP.getFreeHeap());
return false;
}
@@ -475,7 +507,9 @@ void mqtt_callback(char* topic, byte* payload, unsigned int length) {
message = "";
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());
return;
}
@@ -682,10 +716,12 @@ void mqtt_loop(void * parameter) {
}
// Periodically check connection status
if (now - lastCheck > 30000) { // Check every 30 seconds
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();
@@ -700,14 +736,13 @@ bool setupMqtt() {
bool success = loadBambuCredentials();
if (!success) {
Serial.println("Failed to load Bambu credentials");
oledShowMessage("Bambu Credentials Missing");
vTaskDelay(2000 / portTICK_PERIOD_MS);
bambuDisabled = true;
return false;
}
if (success && bambu_ip != "" && bambu_accesscode != "" && bambu_serialnr != "")
{
bambuDisabled = false;
sslClient.setCACert(root_ca);
sslClient.setInsecure();
client.setServer(bambu_ip, 8883);
@@ -764,10 +799,7 @@ bool setupMqtt() {
}
else
{
Serial.println("Fehler: Keine MQTT-Daten vorhanden");
oledShowMessage("Bambu Credentials Missing");
oledShowTopRow();
vTaskDelay(2000 / portTICK_PERIOD_MS);
bambuDisabled = true;
return false;
}
return true;
+2
View File
@@ -30,7 +30,9 @@ extern int ams_count;
extern AMSData ams_data[MAX_AMS];
extern bool autoSendToBambu;
extern int autoSetToBambuSpoolId;
extern bool bambuDisabled;
bool removeBambuCredentials();
bool loadBambuCredentials();
bool saveBambuCredentials(const String& bambu_ip, const String& bambu_serialnr, const String& bambu_accesscode, const bool autoSend, const String& autoSendTime);
bool setupMqtt();
+17
View File
@@ -1,6 +1,23 @@
#include "commonFS.h"
#include <LittleFS.h>
bool removeJsonValue(const char *filename)
{
File file = LittleFS.open(filename, "r");
if (!file)
{
return true;
}
file.close();
if (!LittleFS.remove(filename))
{
Serial.print("Fehler beim Löschen der Datei: ");
Serial.println(filename);
return false;
}
return true;
}
bool saveJsonValue(const char* filename, const JsonDocument& doc) {
File file = LittleFS.open(filename, "w");
if (!file) {
+2 -1
View File
@@ -5,7 +5,8 @@
#include <ArduinoJson.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);
void initializeFileSystem();
+7
View File
@@ -6,6 +6,8 @@
//#define PN532_MOSI 23
//#define PN532_SS 5
//#define PN532_MISO 19
const uint8_t PN532_IRQ = 32;
const uint8_t PN532_RESET = 33;
// ***** PN532
// ***** HX711 (Waage)
@@ -17,6 +19,11 @@ const uint16_t SCALE_LEVEL_WEIGHT = 500;
uint16_t defaultScaleCalibrationValue = 430;
// ***** HX711
// ***** TTP223 (Touch Sensor)
// TTP223 circuit wiring
const uint8_t TTP223_PIN = 25;
// ***** TTP223
// ***** Display
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// On an ESP32: 21(SDA), 22(SCL)
+6 -13
View File
@@ -1,18 +1,16 @@
#pragma once
#ifndef CONFIG_H
#define CONFIG_H
#include <Arduino.h>
// ***** PN532 (RFID)
//#define PN532_SCK 18
//#define PN532_MOSI 23
//#define PN532_SS 5
//#define PN532_MISO 19
// ***** PN532
extern const uint8_t PN532_IRQ;
extern const uint8_t PN532_RESET;
extern const uint8_t LOADCELL_DOUT_PIN;
extern const uint8_t LOADCELL_SCK_PIN;
extern const uint8_t calVal_eepromAdress;
extern const uint16_t SCALE_LEVEL_WEIGHT;
extern const uint8_t TTP223_PIN;
extern const int8_t OLED_RESET;
extern const uint8_t SCREEN_ADDRESS;
@@ -50,9 +48,4 @@ extern uint8_t scaleTaskCore;
extern uint8_t scaleTaskPrio;
extern uint16_t defaultScaleCalibrationValue;
#define PN532_SCK (18)
#define PN532_MISO (19)
#define PN532_MOSI (23)
#define PN532_CS1 (5)
#define PN532_CS2 (4)
#endif
+6 -3
View File
@@ -177,9 +177,12 @@ void oledShowTopRow() {
display.drawBitmap(50, 0, bitmap_off , 16, 16, WHITE);
}
if (spoolman_connected == 1) {
display.drawBitmap(80, 0, bitmap_spoolman_on , 16, 16, WHITE);
} else {
if (spoolmanApiState != API_INIT)
{
display.drawBitmap(80, 0, bitmap_spoolman_on, 16, 16, WHITE);
}
else
{
display.drawBitmap(80, 0, bitmap_off , 16, 16, WHITE);
}
+38 -19
View File
@@ -15,6 +15,7 @@
bool mainTaskWasPaused = 0;
uint8_t scaleTareCounter = 0;
bool touchSensorConnected = false;
// ##### SETUP #####
void setup() {
@@ -39,7 +40,6 @@ void setup() {
setupWebserver(server);
// Spoolman API
// api.cpp
initSpoolman();
// Bambu MQTT
@@ -48,7 +48,16 @@ void setup() {
// NFC Reader
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
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;
int16_t lastWeight = 0;
// WIFI check variables
unsigned long lastWifiCheckTime = 0;
const unsigned long wifiCheckInterval = 60000; // Überprüfe alle 60 Sekunden (60000 ms)
// Button debounce variables
unsigned long lastButtonPress = 0;
const unsigned long debounceDelay = 500; // 500 ms debounce delay
// ##### PROGRAM START #####
void loop() {
unsigned long currentMillis = millis();
// Überprüfe den Status des Touch Sensors
if (touchSensorConnected && digitalRead(TTP223_PIN) == HIGH && currentMillis - lastButtonPress > debounceDelay)
{
lastButtonPress = currentMillis;
scaleTareRequest = true;
}
// Überprüfe regelmäßig die WLAN-Verbindung
if (intervalElapsed(currentMillis, lastWifiCheckTime, wifiCheckInterval)) {
checkWiFiConnection();
@@ -98,9 +119,14 @@ void loop() {
// Wenn Bambu auto set Spool aktiv
if (autoSendToBambu && autoSetToBambuSpoolId > 0) {
if (!bambuDisabled && !bambu_connected)
{
bambu_restart();
}
if (intervalElapsed(currentMillis, lastAutoSetBambuAmsTime, autoSetBambuAmsInterval))
{
if (hasReadRfidTag == 0)
if (nfcReaderState == NFC_IDLE)
{
lastAutoSetBambuAmsTime = currentMillis;
oledShowMessage("Auto Set " + String(autoSetBambuAmsCounter - autoAmsCounter) + "s");
@@ -134,7 +160,7 @@ void loop() {
// Ausgabe der Waage auf Display
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);
}
@@ -147,27 +173,18 @@ void loop() {
// 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;
// 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)
{
scaleTareCounter++;
scale_tare_counter++;
}
else
{
scaleTareRequest = true;
scaleTareCounter = 0;
}
}
else
{
scaleTareCounter = 0;
scale_tare_counter = 0;
}
// Prüfen ob das Gewicht gleich bleibt und dann senden
@@ -183,7 +200,8 @@ void loop() {
}
// 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;
}
@@ -191,7 +209,8 @@ void loop() {
lastWeight = weight;
// 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");
if (updateSpoolWeight(spoolId, weight))
{
+70 -38
View File
@@ -32,7 +32,7 @@ String spoolId = "";
String nfcJsonData = "";
volatile bool pauseBambuMqttTask = false;
volatile uint8_t hasReadRfidTag = 0;
volatile nfcReaderStateType nfcReaderState = NFC_IDLE;
// 0 = nicht gelesen
// 1 = erfolgreich gelesen
// 2 = fehler beim Lesen
@@ -185,10 +185,10 @@ void processTag(uint8_t *uid, uint8_t uidLength, uint8_t readerNumber) {
void processNfcData(uint8_t *data, String tagId) {
// Process the data and send it via WebSocket
if (decodeNdefAndReturnJson(data)) {
hasReadRfidTag = 1;
nfcReaderState = NFC_READ_SUCCESS;
sendNfcData(nullptr);
} else {
hasReadRfidTag = 2;
nfcReaderState = NFC_READ_ERROR;
oledShowMessage("NFC-Tag unknown");
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
@@ -407,7 +407,7 @@ void writeJsonToTag(void *parameter) {
Serial.println("Erstelle NDEF-Message...");
Serial.println(payload);
hasReadRfidTag = 3;
nfcReaderState = NFC_WRITING;
vTaskSuspend(RfidReaderTask);
vTaskDelay(50 / portTICK_PERIOD_MS);
@@ -462,7 +462,7 @@ void writeJsonToTag(void *parameter) {
Serial.println("NDEF-Message erfolgreich auf den Tag geschrieben");
oledShowIcon("success");
vTaskDelay(1000 / portTICK_PERIOD_MS);
hasReadRfidTag = 5;
nfcReaderState = NFC_WRITE_SUCCESS;
sendNfcData(nullptr);
pauseBambuMqttTask = false;
@@ -481,13 +481,13 @@ void writeJsonToTag(void *parameter) {
Serial.println("Fehler beim Schreiben der NDEF-Message auf den Tag");
oledShowIcon("failed");
vTaskDelay(2000 / portTICK_PERIOD_MS);
hasReadRfidTag = 4;
nfcReaderState = NFC_WRITE_ERROR;
}
} else {
Serial.println("Fehler: Kein Tag zu schreiben gefunden.");
oledShowMessage("No NFC-Tag found");
vTaskDelay(2000 / portTICK_PERIOD_MS);
hasReadRfidTag = 0;
nfcReaderState = NFC_IDLE;
}
sendWriteResult(nullptr, success);
@@ -503,7 +503,7 @@ void startWriteJsonToTag(const char* payload) {
char* payloadCopy = strdup(payload);
// Task nicht mehrfach starten
if (hasReadRfidTag != 3) {
if (nfcReaderState != NFC_WRITING) {
// Erstelle die Task
xTaskCreate(
writeJsonToTag, // Task-Funktion
@@ -518,51 +518,61 @@ void startWriteJsonToTag(const char* payload) {
void scanRfidTask(void * parameter) {
Serial.println("RFID Task gestartet");
for(;;) {
if (hasReadRfidTag != 3) {
if (nfcReaderState != NFC_WRITING)
{
yield();
uint8_t success = 0;
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };
uint8_t uid[] = {0, 0, 0, 0, 0, 0, 0};
uint8_t uidLength;
Adafruit_PN532* activeReader = nullptr;
Adafruit_PN532 *activeReader = nullptr;
// Try first reader with increased timeout
success = nfc1.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 150);
if (success) {
if (success)
{
activeReader = &nfc1;
} else {
}
else
{
delay(50); // Small delay between readers
// Try second reader with increased timeout
success = nfc2.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 150);
if (success) {
if (success)
{
activeReader = &nfc2;
}
}
foundNfcTag(nullptr, success);
if (success && hasReadRfidTag != 1 && activeReader != nullptr) {
if (success && nfcReaderState != NFC_READ_SUCCESS && activeReader != nullptr)
{
Serial.println("Found an ISO14443A card");
hasReadRfidTag = 6;
nfcReaderState = NFC_READING;
oledShowIcon("transfer");
vTaskDelay(500 / portTICK_PERIOD_MS);
if (uidLength == 7) {
if (uidLength == 7)
{
uint16_t tagSize = readTagSize(*activeReader);
if(tagSize > 0) {
uint8_t* data = (uint8_t*)malloc(tagSize);
if (tagSize > 0)
{
uint8_t *data = (uint8_t *)malloc(tagSize);
memset(data, 0, tagSize);
Serial.println("Seems to be an NTAG2xx tag (7 byte UID)");
uint8_t numPages = readTagSize(*activeReader)/4;
for (uint8_t i = 4; i < 4+numPages; i++) {
if (!activeReader->ntag2xx_ReadPage(i, data+(i-4) * 4)) {
uint8_t numPages = readTagSize(*activeReader) / 4;
for (uint8_t i = 4; i < 4 + numPages; i++)
{
if (!activeReader->ntag2xx_ReadPage(i, data + (i - 4) * 4))
{
break;
}
if (data[(i - 4) * 4] == 0xFE) {
if (data[(i - 4) * 4] == 0xFE)
{
break;
}
@@ -571,29 +581,38 @@ void scanRfidTask(void * parameter) {
vTaskDelay(pdMS_TO_TICKS(5)); // Increased delay between page reads
}
if (!decodeNdefAndReturnJson(data)) {
if (!decodeNdefAndReturnJson(data))
{
oledShowMessage("NFC-Tag unknown");
vTaskDelay(2000 / portTICK_PERIOD_MS);
hasReadRfidTag = 2;
} else {
hasReadRfidTag = 1;
nfcReaderState = NFC_READ_ERROR;
}
else
{
nfcReaderState = NFC_READ_SUCCESS;
}
free(data);
} else {
oledShowMessage("NFC-Tag read error");
hasReadRfidTag = 2;
}
} else {
else
{
oledShowMessage("NFC-Tag read error");
nfcReaderState = NFC_READ_ERROR;
}
}
else
{
Serial.println("This doesn't seem to be an NTAG2xx tag (UUID length != 7 bytes)!");
}
}
if (!success && hasReadRfidTag > 0) {
hasReadRfidTag = 0;
if (!success && nfcReaderState != NFC_IDLE)
{
nfcReaderState = NFC_IDLE;
nfcJsonData = "";
Serial.println("Tag entfernt");
if (!autoSendToBambu) oledShowWeight(weight);
if (!autoSendToBambu)
oledShowWeight(weight);
}
sendNfcData(nullptr);
@@ -601,7 +620,6 @@ void scanRfidTask(void * parameter) {
}
yield();
}
}
void startNfc() {
initNfc();
@@ -621,6 +639,20 @@ void startNfc() {
}
}
String createTagId(uint8_t *uid, uint8_t uidLength) {
// Implementierung der Funktion
String createTagId(uint8_t *uid, uint8_t uidLength)
{
String tagId = ""; // Initialisieren Sie einen leeren String
// Erstellen Sie die Tag-ID basierend auf dem UID
for (uint8_t i = 0; i < uidLength; i++)
{
tagId += String(uid[i], HEX); // Konvertieren Sie die UID in einen String
if (i < uidLength - 1)
{
tagId += ":"; // Fügen Sie einen Trennstrich hinzu, wenn es nicht das letzte Element ist
}
}
return tagId; // Geben Sie die erstellte Tag-ID zurück
Serial.println("tagID:" + tagId);
}
+11 -1
View File
@@ -2,6 +2,16 @@
#include <Arduino.h>
#include <Adafruit_PN532.h>
typedef enum
{
NFC_IDLE,
NFC_READING,
NFC_READ_SUCCESS,
NFC_READ_ERROR,
NFC_WRITING,
NFC_WRITE_SUCCESS,
NFC_WRITE_ERROR
} nfcReaderStateType;
void startNfc();
void startWriteJsonToTag(const char* payload);
@@ -14,7 +24,7 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage);
extern TaskHandle_t RfidReaderTask;
extern String nfcJsonData;
extern String spoolId;
extern volatile uint8_t hasReadRfidTag;
extern volatile nfcReaderStateType nfcReaderState;
extern volatile bool pauseBambuMqttTask;
// Function declarations
+41 -3
View File
@@ -14,6 +14,7 @@ TaskHandle_t ScaleTask;
int16_t weight = 0;
uint8_t weigthCouterToApi = 0;
uint8_t scale_tare_counter = 0;
bool scaleTareRequest = false;
uint8_t pauseMainTask = 0;
uint8_t scaleCalibrated = 1;
@@ -21,9 +22,26 @@ uint8_t scaleCalibrated = 1;
Preferences preferences;
const char* NVS_NAMESPACE = "scale";
const char* NVS_KEY_CALIBRATION = "cal_value";
const char *NVS_KEY_AUTOTARE = "auto_tare";
bool autoTare = true;
// ##### Funktionen für Waage #####
uint8_t 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");
scale.tare();
@@ -38,11 +56,23 @@ void scale_loop(void * parameter) {
for(;;) {
if (scale.is_ready())
{
// Waage nochmal Taren, wenn zu lange Abweichung
// Waage automatisch Taren, wenn zu lange Abweichung
if (autoTare && scale_tare_counter >= 5)
{
Serial.println("Auto Tare scale");
scale.tare();
scale_tare_counter = 0;
}
// Waage manuell Taren
if (scaleTareRequest == true)
{
Serial.println("Re-Tare scale");
oledShowMessage("TARE Scale");
vTaskDelay(pdMS_TO_TICKS(1000));
scale.tare();
vTaskDelay(pdMS_TO_TICKS(1000));
oledShowWeight(0);
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");
float calibrationValue;
// NVS lesen
preferences.begin(NVS_NAMESPACE, true); // true = readonly
calibrationValue = preferences.getFloat(NVS_KEY_CALIBRATION, defaultScaleCalibrationValue);
// auto Tare
// Wenn Touch Sensor verbunden, dann autoTare auf false setzen
// Danach prüfen was in NVS gespeichert ist
autoTare = (touchSensorConnected) ? false : true;
autoTare = preferences.getBool(NVS_KEY_AUTOTARE, autoTare);
preferences.end();
Serial.print("Read Scale Calibration Value ");
+4 -2
View File
@@ -4,17 +4,19 @@
#include <Arduino.h>
#include "HX711.h"
uint8_t start_scale();
uint8_t setAutoTare(bool autoTareValue);
uint8_t start_scale(bool touchSensorConnected);
uint8_t calibrate_scale();
uint8_t tareScale();
extern HX711 scale;
extern int16_t weight;
extern uint8_t weigthCouterToApi;
extern uint8_t scale_tare_counter;
extern uint8_t scaleTareRequest;
extern uint8_t pauseMainTask;
extern uint8_t scaleCalibrated;
extern bool autoTare;
extern TaskHandle_t ScaleTask;
+65 -36
View File
@@ -22,14 +22,13 @@ AsyncWebServer server(webserverPort);
AsyncWebSocket ws("/ws");
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) {
if (type == WS_EVT_CONNECT) {
Serial.println("Neuer Client verbunden!");
// Sende die AMS-Daten an den neuen Client
sendAmsData(client);
if (!bambuDisabled) sendAmsData(client);
sendNfcData(client);
foundNfcTag(client, 0);
sendWriteResult(client, 3);
@@ -43,6 +42,7 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
String message = String((char*)data);
JsonDocument doc;
deserializeJson(doc, message);
bool spoolmanConnected = (spoolmanApiState != API_INIT);
if (doc["type"] == "heartbeat") {
// Sende Heartbeat-Antwort
@@ -50,7 +50,7 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
"\"type\":\"heartbeat\","
"\"freeHeap\":" + String(ESP.getFreeHeap()/1024) + ","
"\"bambu_connected\":" + String(bambu_connected) + ","
"\"spoolman_connected\":" + String(spoolman_connected) + ""
"\"spoolman_connected\":" + String(spoolmanConnected) + ""
"}");
}
@@ -73,6 +73,11 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
success = calibrate_scale();
}
if (doc["payload"] == "setAutoTare")
{
success = setAutoTare(doc["enabled"].as<bool>());
}
if (success) {
ws.textAll("{\"type\":\"scale\",\"payload\":\"success\"}");
} else {
@@ -139,34 +144,33 @@ void foundNfcTag(AsyncWebSocketClient *client, uint8_t success) {
}
void sendNfcData(AsyncWebSocketClient *client) {
if (lastHasReadRfidTag == hasReadRfidTag) return;
if (hasReadRfidTag == 0) {
if (lastnfcReaderState == nfcReaderState)
return;
// TBD: Why is there no status for reading the tag?
switch (nfcReaderState)
{
case NFC_IDLE:
ws.textAll("{\"type\":\"nfcData\", \"payload\":{}}");
}
else if (hasReadRfidTag == 1) {
break;
case NFC_READ_SUCCESS:
ws.textAll("{\"type\":\"nfcData\", \"payload\":" + nfcJsonData + "}");
}
else if (hasReadRfidTag == 2)
{
break;
case NFC_READ_ERROR:
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Empty Tag or Data not readable\"}}");
}
else if (hasReadRfidTag == 3)
{
break;
case NFC_WRITING:
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Schreibe Tag...\"}}");
}
else if (hasReadRfidTag == 4)
{
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Error writing to Tag\"}}");
}
else if (hasReadRfidTag == 5)
{
break;
case NFC_WRITE_SUCCESS:
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Tag erfolgreich geschrieben\"}}");
}
else
{
break;
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\"}}");
}
lastHasReadRfidTag = hasReadRfidTag;
lastnfcReaderState = nfcReaderState;
}
void sendAmsData(AsyncWebSocketClient *client) {
@@ -202,18 +206,24 @@ void setupWebserver(AsyncWebServer &server) {
});
// Route für Waage
server.on("/waage", HTTP_GET, [](AsyncWebServerRequest *request){
server.on("/waage", HTTP_GET, [](AsyncWebServerRequest *request)
{
Serial.println("Anfrage für /waage erhalten");
AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/waage.html.gz", "text/html");
response->addHeader("Content-Encoding", "gzip");
response->addHeader("Cache-Control", CACHE_CONTROL);
request->send(response);
});
//AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/waage.html.gz", "text/html");
//response->addHeader("Content-Encoding", "gzip");
//response->addHeader("Cache-Control", CACHE_CONTROL);
String html = loadHtmlWithHeader("/waage.html");
html.replace("{{autoTare}}", (autoTare) ? "checked" : "");
request->send(200, "text/html", html); });
// Route für RFID
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
Serial.println("Anfrage für /rfid erhalten");
AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/rfid.html.gz", "text/html");
String page = (bambuDisabled) ? "/rfid.html.gz" : "/rfid_bambu.html.gz";
AsyncWebServerResponse *response = request->beginResponse(LittleFS, page, "text/html");
response->addHeader("Content-Encoding", "gzip");
response->addHeader("Cache-Control", CACHE_CONTROL);
request->send(response);
@@ -286,6 +296,16 @@ void setupWebserver(AsyncWebServer &server) {
}
String url = request->getParam("url")->value();
if (url.indexOf("http://") == -1 && url.indexOf("https://") == -1)
{
url = "http://" + url;
}
// Remove trailing slash if exists
if (url.length() > 0 && url.charAt(url.length() - 1) == '/')
{
url = url.substring(0, url.length() - 1);
}
bool octoEnabled = (request->getParam("octoEnabled")->value() == "true") ? true : false;
String octoUrl = request->getParam("octoUrl")->value();
String octoToken = (request->getParam("octoToken")->value() != "") ? request->getParam("octoToken")->value() : "";
@@ -300,8 +320,18 @@ void setupWebserver(AsyncWebServer &server) {
request->send(200, "application/json", jsonResponse);
});
// Route für das Überprüfen der Spoolman-Instanz
server.on("/api/bambu", HTTP_GET, [](AsyncWebServerRequest *request){
// Route für das Überprüfen der Bambu-Instanz
server.on("/api/bambu", HTTP_GET, [](AsyncWebServerRequest *request)
{
if (request->hasParam("remove")) {
if (removeBambuCredentials()) {
request->send(200, "application/json", "{\"success\": true}");
} else {
request->send(500, "application/json", "{\"success\": false, \"error\": \"Fehler beim Löschen der Bambu-Credentials\"}");
}
return;
}
if (!request->hasParam("bambu_ip") || !request->hasParam("bambu_serialnr") || !request->hasParam("bambu_accesscode")) {
request->send(400, "application/json", "{\"success\": false, \"error\": \"Missing parameter\"}");
return;
@@ -325,8 +355,7 @@ void setupWebserver(AsyncWebServer &server) {
bool success = saveBambuCredentials(bambu_ip, bambu_serialnr, bambu_accesscode, autoSend, autoSendTime);
request->send(200, "application/json", "{\"healthy\": " + String(success ? "true" : "false") + "}");
});
request->send(200, "application/json", "{\"healthy\": " + String(success ? "true" : "false") + "}"); });
// Route für das Überprüfen der Spoolman-Instanz
server.on("/reboot", HTTP_GET, [](AsyncWebServerRequest *request){
+1 -1
View File
@@ -59,7 +59,7 @@ void initWiFi() {
if(wm_nonblocking) wm.setConfigPortalBlocking(false);
//wm.setConfigPortalTimeout(320); // Portal nach 5min schließen
wm.setWiFiAutoReconnect(true);
wm.setConnectTimeout(5);
wm.setConnectTimeout(10);
oledShowTopRow();
oledShowMessage("WiFi Setup");