Compare commits

...

25 Commits

Author SHA1 Message Date
739fe7e764 docs: update changelog and header for version v1.5.6
Some checks failed
Release Workflow / detect-provider (push) Successful in 4s
Release Workflow / github-release (push) Has been skipped
Release Workflow / gitea-release (push) Failing after 2m22s
2025-07-28 09:32:35 +02:00
5f8953a19d docs: update webpages for version v1.5.6 2025-07-28 09:32:35 +02:00
c919eeb848 docs: update platformio.ini for version v1.5.6 2025-07-28 09:32:30 +02:00
43177c670e Merge pull request #42 from janecker/configuration_nvs_storage
Changes configuration storage of spoolman and bambu values
2025-07-28 09:31:33 +02:00
1b50694f5f Merge branch 'main' into configuration_nvs_storage 2025-07-28 09:31:23 +02:00
48edde8557 Merge pull request #41 from janecker/memory_leak_fixes
Memory leak fixes
2025-07-28 09:26:30 +02:00
Jan Philipp Ecker
cb5d8ac10a Changes configuration storage of spoolman and bambu values
Change that moves configuration values of spoolman and bambu credentials to use NVS storage. Also fixes some typos and missing translation.
2025-07-27 17:33:09 +02:00
Jan Philipp Ecker
bf48c6d4e1 Fixes compiler warnings in nfc
Replaces the depricated function call containsKey() with is<T>() of JsonDocument.
2025-07-26 22:52:10 +02:00
Jan Philipp Ecker
5d2d5e9ee1 Adds ENABLE_HEAP_DEBUGGING define as comment to the build flags
Adds the new ENABLE_HEAP_DEBUGGING define to the build falgs. The option is commented out, but it makes it easier to quickly enable it
2025-07-26 22:50:08 +02:00
Jan Philipp Ecker
7e76612bb4 Adds data directory and further .vscode files to to .gitignore
Adds the whole data folder that is created during build of the project and further visual studio code related files to the .gitignore file.
2025-07-26 22:39:37 +02:00
Jan Philipp Ecker
f038020042 Memory leak fixes in api and nfc, location tag fix
Fixes multiple potential memory leaks in API and NFC. Also fixes an issue in the new locaiton tag feature that could lead to multiple parallel API requests. This could cause memory leak issues but also result in wrong weights being registered for a spool.
2025-07-26 22:36:04 +02:00
Jan Philipp Ecker
8343fe887b Introduces new heap debugging feature and fixes some memory leaks in website feature
Introduces a new define HEAP_DEBUG_MESSAGE(location) that can be used to instrument the code to get heap information output on the Serial output. It can be enabled via the define ENABLE_HEAP_DEBUGGING. Also fixes some memory leaks in the website part of the project.
2025-07-26 22:14:58 +02:00
3bb6c1caf5 docs: update changelog and header for version v1.5.5
All checks were successful
Release Workflow / detect-provider (push) Successful in 1m6s
Release Workflow / github-release (push) Has been skipped
Release Workflow / gitea-release (push) Successful in 2m52s
2025-07-22 17:36:45 +02:00
37df07f102 docs: update platformio.ini for version v1.5.5 2025-07-22 17:36:45 +02:00
8484c1310b Merge pull request #40 from janecker/location_bambu_fix
Fixes some issues with the new location tags
2025-07-22 17:35:02 +02:00
Jan Philipp Ecker
fd7b4c25b3 Fixes some issues with the new location tags
Fixes an issue where the location dropdown is not visible if the Bambu integration is active. Adds support for the "NFC-Tag" view on the webpage, it now also shows info about the location tags. Revers a change that was not supposed to go into main where the amount of data written to the spool tag is reduced to only the sm_id.
2025-07-22 10:47:47 +02:00
d490b116b9 docs: update changelog and header for version v1.5.4
All checks were successful
Release Workflow / detect-provider (push) Successful in 1m10s
Release Workflow / github-release (push) Has been skipped
Release Workflow / gitea-release (push) Successful in 3m52s
2025-07-22 06:36:16 +02:00
5bc6192b6f docs: update platformio.ini for version v1.5.4 2025-07-22 06:36:16 +02:00
2202d9a1aa Merge branch 'main' of github.com:ManuelW77/Filaman 2025-07-22 06:35:13 +02:00
7dbca0ab87 Merge pull request #39 from janecker/location_tags
Adds new feature to write and read location tags
2025-07-22 06:32:44 +02:00
24b3521f83 Merge pull request #38 from janecker/scale_debouncing
Adds slight debouncing to the scale loop weight logic
2025-07-22 06:32:31 +02:00
6c9f290bac fix: uncomment monitor_port configuration in platformio.ini 2025-07-22 06:31:51 +02:00
Jan Philipp Ecker
eab937d6ca Adds new feature to write and read location tags
Location tags can be written via the website. If a location tag is read after reading a spool tag, the location of the spool will be updated in spoolman to the location from the tag.
2025-07-21 21:03:55 +02:00
Jan Philipp Ecker
27ef8399e4 Adds slight debouncing to the scale loop weight logic
Adds slight debouncing to the scale loop to prevent jitter of the
weight displayed on the screen.
2025-06-19 10:08:15 +02:00
2920159f32 add loadcell desc. 2025-05-02 16:44:57 +02:00
26 changed files with 534 additions and 187 deletions

8
.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
.vscode/extensions.json
.vscode/settings.json
data

View File

@@ -1,5 +1,51 @@
# Changelog
## [1.5.6] - 2025-07-28
### Added
- Adds ENABLE_HEAP_DEBUGGING define as comment to the build flags
- Adds data directory and further .vscode files to to .gitignore
- Introduces new heap debugging feature and fixes some memory leaks in website feature
### Changed
- update webpages for version v1.5.6
- update platformio.ini for version v1.5.6
- Merge pull request #42 from janecker/configuration_nvs_storage
- Merge branch 'main' into configuration_nvs_storage
- Changes configuration storage of spoolman and bambu values
### Fixed
- Merge pull request #41 from janecker/memory_leak_fixes
- Fixes compiler warnings in nfc
- Memory leak fixes in api and nfc, location tag fix
## [1.5.5] - 2025-07-22
### Added
- Fixes some issues with the new location tags
### Changed
- update platformio.ini for version v1.5.5
### Fixed
- Merge pull request #40 from janecker/location_bambu_fix
## [1.5.4] - 2025-07-22
### Added
- Adds new feature to write and read location tags
- Adds slight debouncing to the scale loop weight logic
- add loadcell desc.
### Changed
- update platformio.ini for version v1.5.4
- Merge branch 'main' of github.com:ManuelW77/Filaman
- Merge pull request #39 from janecker/location_tags
- Merge pull request #38 from janecker/scale_debouncing
### Fixed
- uncomment monitor_port configuration in platformio.ini
## [1.5.3] - 2025-04-25
### Changed
- update platformio.ini for version v1.5.3

View File

@@ -90,6 +90,12 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v)
![myWiring](./img/IMG_2589.jpeg)
![myWiring](./img/IMG_2590.jpeg)
*Die Wägezelle wird bei den meisten HX711 Modulen folgendermaßen verkabelt:
E+ rot
E- schwarz
A- weiß
A+ grün*
## Software-Abhängigkeiten
### ESP32-Bibliotheken

View File

@@ -94,6 +94,12 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v)
![myWiring](./img/IMG_2589.jpeg)
![myWiring](./img/IMG_2590.jpeg)
*The load cell is connected to most HX711 modules as follows:
E+ red
E- black
A- white
A+ green*
## Software Dependencies
### ESP32 Libraries

BIN
html/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1 @@
{"bambu_ip": "192.168.1.14", "bambu_accesscode": "22772584", "bambu_serialnr": "01P00C492600230","autoSendToBambu":true,"autoSendTime": 60}

View File

@@ -139,6 +139,18 @@
<p id="nfcInfo" class="nfc-status"></p>
<button id="writeNfcButton" class="btn btn-primary hidden" onclick="writeNfcTag()">Write Tag</button>
</div>
<div class="feature-box">
<h2>Spoolman Locations</h2>
<label for="locationSelect">Location:</label>
<div style="display: flex; justify-content: space-between; align-items: center;">
<select id="locationSelect" class="styled-select">
<option value="">Please choose...</option>
</select>
</div>
<p id="nfcInfoLocation" class="nfc-status"></p>
<button id="writeLocationNfcButton" class="btn btn-primary hidden" onclick="writeLocationNfcTag()">Write Location Tag</button>
</div>
</div>
</div>

View File

@@ -555,7 +555,10 @@ function updateNfcData(data) {
}
// HTML für die Datenanzeige erstellen
let html = `
let html = "";
if(data.sm_id){
html = `
<div class="nfc-card-data" style="margin-top: 10px;">
<p><strong>Brand:</strong> ${data.brand || 'N/A'}</p>
<p><strong>Type:</strong> ${data.type || 'N/A'} ${data.color_hex ? `<span style="
@@ -568,10 +571,27 @@ function updateNfcData(data) {
border-radius: 3px;
margin-left: 5px;
"></span>` : ''}</p>
`;
`;
// Spoolman ID anzeigen
html += `<p><strong>Spoolman ID:</strong> ${data.sm_id || 'No Spoolman ID'}</p>`;
// Spoolman ID anzeigen
html += `<p><strong>Spoolman ID:</strong> ${data.sm_id || 'No Spoolman ID'}</p>`;
}
else if(data.location)
{
html = `
<div class="nfc-card-data" style="margin-top: 10px;">
<p><strong>Location:</strong> ${data.location || 'N/A'}</p>
`;
}
else
{
html = `
<div class="nfc-card-data" style="margin-top: 10px;">
<p><strong>Unknown tag</strong></p>
`;
}
// Nur wenn eine sm_id vorhanden ist, aktualisiere die Dropdowns
if (data.sm_id) {
@@ -647,16 +667,56 @@ function writeNfcTag() {
}
}
function writeLocationNfcTag() {
const selectedText = document.getElementById("locationSelect").value;
if (selectedText === "Please choose...") {
alert('Please select a location first.');
return;
}
// Erstelle das NFC-Datenpaket mit korrekten Datentypen
const nfcData = {
location: String(selectedText)
};
if (socket?.readyState === WebSocket.OPEN) {
const writeButton = document.getElementById("writeLocationNfcButton");
writeButton.classList.add("writing");
writeButton.textContent = "Writing";
socket.send(JSON.stringify({
type: 'writeNfcTag',
payload: nfcData
}));
} else {
alert('Not connected to Server. Please check connection.');
}
}
function handleWriteNfcTagResponse(success) {
const writeButton = document.getElementById("writeNfcButton");
writeButton.classList.remove("writing");
writeButton.classList.add(success ? "success" : "error");
writeButton.textContent = success ? "Write success" : "Write failed";
const writeLocationButton = document.getElementById("writeLocationNfcButton");
if(writeButton.classList.contains("writing")){
writeButton.classList.remove("writing");
writeButton.classList.add(success ? "success" : "error");
writeButton.textContent = success ? "Write success" : "Write failed";
setTimeout(() => {
writeButton.classList.remove("success", "error");
writeButton.textContent = "Write Tag";
}, 5000);
setTimeout(() => {
writeButton.classList.remove("success", "error");
writeButton.textContent = "Write Tag";
}, 5000);
}
if(writeLocationButton.classList.contains("writing")){
writeLocationButton.classList.remove("writing");
writeLocationButton.classList.add(success ? "success" : "error");
writeLocationButton.textContent = success ? "Write success" : "Write failed";
setTimeout(() => {
writeLocationButton.classList.remove("success", "error");
writeLocationButton.textContent = "Write Location Tag";
}, 5000);
}
}
function showNotification(message, isSuccess) {

View File

@@ -139,6 +139,18 @@
<p id="nfcInfo" class="nfc-status"></p>
<button id="writeNfcButton" class="btn btn-primary hidden" onclick="writeNfcTag()">Write Tag</button>
</div>
<div class="feature-box">
<h2>Spoolman Locations</h2>
<label for="locationSelect">Location:</label>
<div style="display: flex; justify-content: space-between; align-items: center;">
<select id="locationSelect" class="styled-select">
<option value="">Please choose...</option>
</select>
</div>
<p id="nfcInfoLocation" class="nfc-status"></p>
<button id="writeLocationNfcButton" class="btn btn-primary hidden" onclick="writeLocationNfcTag()">Write Location Tag</button>
</div>
</div>
<!-- Rechte Spalte -->

View File

@@ -146,20 +146,20 @@
<div class="card">
<div class="card-body">
<h5 class="card-title">Set URL/IP to your Spoolman-Instanz</h5>
<input type="text" id="spoolmanUrl" placeholder="http://ip-or-url-of-your-spoolman-instanz:port">
<h5 class="card-title">If you want to enable sending Spool to Spoolman Octoprint Plugin:</h5>
<h5 class="card-title">Set URL/IP to your Spoolman instance</h5>
<input type="text" id="spoolmanUrl" onkeydown="if(event.keyCode == 13) document.getElementById('btnSaveSpoolmanUrl').click()" placeholder="http://ip-or-url-of-your-spoolman-instance:port">
<h5 class="card-title">If you want to enable sending the spool to the Spoolman Octoprint plugin:</h5>
<p>
<input type="checkbox" id="spoolmanOctoEnabled" {{spoolmanOctoEnabled}} onchange="toggleOctoFields()"> Send to Octo-Plugin
</p>
<div id="octoFields" style="display: none;">
<p>
<input type="text" id="spoolmanOctoUrl" placeholder="http://ip-or-url-of-your-octoprint-instanz:port" value="{{spoolmanOctoUrl}}">
<input type="text" id="spoolmanOctoUrl" placeholder="http://ip-or-url-of-your-octoprint-instance:port" value="{{spoolmanOctoUrl}}">
<input type="text" id="spoolmanOctoToken" placeholder="Your Octoprint Token" value="{{spoolmanOctoToken}}">
</p>
</div>
<button onclick="checkSpoolmanInstance()">Save Spoolman URL</button>
<button id="btnSaveSpoolmanUrl" onclick="checkSpoolmanInstance()">Save Spoolman URL</button>
<p id="statusMessage"></p>
</div>
</div>
@@ -169,16 +169,16 @@
<h5 class="card-title">Bambu Lab Printer Credentials</h5>
<div class="bambu-settings">
<div class="input-group">
<label for="bambuIp">Bambu Drucker IP-Adresse:</label>
<label for="bambuIp">Bambu Printer IP Address:</label>
<input type="text" id="bambuIp" placeholder="192.168.1.xxx" value="{{bambuIp}}">
</div>
<div class="input-group">
<label for="bambuSerial">Drucker Seriennummer:</label>
<label for="bambuSerial">Printer Serial Number:</label>
<input type="text" id="bambuSerial" placeholder="BBLXXXXXXXX" value="{{bambuSerial}}">
</div>
<div class="input-group">
<label for="bambuCode">Access Code:</label>
<input type="text" id="bambuCode" placeholder="Access Code vom Drucker" value="{{bambuCode}}">
<input type="text" id="bambuCode" placeholder="Access Code of the printer" value="{{bambuCode}}">
</div>
<hr>
<p>If activated, FilaMan will automatically update the next filled tray with the last scanned and weighed spool.</p>

View File

@@ -1,6 +1,7 @@
// Globale Variablen
let spoolmanUrl = '';
let spoolsData = [];
let locationData = [];
// Hilfsfunktionen für Datenmanipulation
function processSpoolData(data) {
@@ -133,6 +134,26 @@ function populateVendorDropdown(data, selectedSmId = null) {
}
}
// Dropdown-Funktionen
function populateLocationDropdown(data) {
const locationSelect = document.getElementById("locationSelect");
if (!locationSelect) {
console.error('locationSelect Element nicht gefunden');
return;
}
locationSelect.innerHTML = '<option value="">Bitte wählen...</option>';
// Dropdown mit gefilterten Herstellern befüllen - alphabetisch sortiert
Object.entries(data)
.sort(([, nameA], [, nameB]) => nameA.localeCompare(nameB)) // Sort vendors alphabetically by name
.forEach(([id, name]) => {
const option = document.createElement("option");
option.value = name;
option.textContent = name;
locationSelect.appendChild(option);
});
}
function updateFilamentDropdown(selectedSmId = null) {
const vendorId = document.getElementById("vendorSelect").value;
const dropdownContentInner = document.getElementById("filament-dropdown-content");
@@ -208,6 +229,13 @@ function updateFilamentDropdown(selectedSmId = null) {
}
}
function updateLocationSelect(){
const writeLocationNfcButton = document.getElementById('writeLocationNfcButton');
if(writeLocationNfcButton){
writeLocationNfcButton.classList.remove("hidden");
}
}
function selectFilament(spool) {
const selectedColor = document.getElementById("selected-color");
const selectedText = document.getElementById("selected-filament");
@@ -261,10 +289,18 @@ async function initSpoolman() {
const fetchedData = await fetchSpoolData();
spoolsData = processSpoolData(fetchedData);
document.dispatchEvent(new CustomEvent('spoolDataLoaded', {
detail: spoolsData
}));
locationData = await fetchLocationData();
document.dispatchEvent(new CustomEvent('locationDataLoaded', {
detail: locationData
}));
} catch (error) {
console.error('Fehler beim Initialisieren von Spoolman:', error);
document.dispatchEvent(new CustomEvent('spoolmanError', {
@@ -292,6 +328,25 @@ async function fetchSpoolData() {
}
}
async function fetchLocationData() {
try {
if (!spoolmanUrl) {
throw new Error('Spoolman URL ist nicht initialisiert');
}
const response = await fetch(`${spoolmanUrl}/api/v1/location`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error('Fehler beim Abrufen der Location-Daten:', error);
return [];
}
}
// Event Listener
document.addEventListener('DOMContentLoaded', () => {
initSpoolman();
@@ -300,6 +355,11 @@ document.addEventListener('DOMContentLoaded', () => {
if (vendorSelect) {
vendorSelect.addEventListener('change', () => updateFilamentDropdown());
}
const locationSelect = document.getElementById('locationSelect');
if (locationSelect) {
locationSelect.addEventListener('change', () => updateLocationSelect());
}
const onlyWithoutSmId = document.getElementById('onlyWithoutSmId');
if (onlyWithoutSmId) {
@@ -312,6 +372,10 @@ document.addEventListener('DOMContentLoaded', () => {
document.addEventListener('spoolDataLoaded', (event) => {
populateVendorDropdown(event.detail);
});
document.addEventListener('locationDataLoaded', (event) => {
populateLocationDropdown(event.detail);
});
window.onclick = function(event) {
if (!event.target.closest('.custom-dropdown')) {
@@ -342,6 +406,7 @@ window.getSpoolData = () => spoolsData;
window.setSpoolData = (data) => { spoolsData = data; };
window.reloadSpoolData = initSpoolman;
window.populateVendorDropdown = populateVendorDropdown;
window.populateLocationDropdown = populateLocationDropdown;
window.updateFilamentDropdown = updateFilamentDropdown;
window.toggleFilamentDropdown = () => {
const content = document.getElementById("filament-dropdown-content");

1
html/spoolman_url.json Normal file
View File

@@ -0,0 +1 @@
{"url": "http://192.168.1.5:7912", "octoEnabled": true, "octoUrl": "http://192.168.1.17:5001", "octoToken": "O5zZ58mXRAyeGpVEj2ZZj-UPAPqJ2N7JgtD36mw1M4g"}

View File

@@ -971,31 +971,35 @@ input[type="submit"]:disabled,
}
/* Schreib-Button */
#writeNfcButton {
#writeNfcButton, #writeLocationNfcButton {
background-color: #007bff;
color: white;
transition: background-color 0.3s, color 0.3s;
width: 160px;
}
#writeNfcButton.writing {
#writeNfcButton.writing, #writeLocationNfcButton.writing {
background-color: #ffc107;
color: black;
width: 160px;
}
#writeNfcButton.success {
#writeNfcButton.success, #writeLocationNfcButton.success {
background-color: #28a745;
color: white;
width: 160px;
}
#writeNfcButton.error {
#writeNfcButton.error, #writeLocationNfcButton.error {
background-color: #dc3545;
color: white;
width: 160px;
}
#writeLocationNfcButton{
width: 250px;
}
@keyframes dots {
0% { content: ""; }
33% { content: "."; }
@@ -1003,7 +1007,7 @@ input[type="submit"]:disabled,
100% { content: "..."; }
}
#writeNfcButton.writing::after {
#writeNfcButton.writing::after, #writeLocationNfcButton.writing::after {
content: "...";
animation: dots 1s steps(3, end) infinite;
}

View File

@@ -9,7 +9,7 @@
; https://docs.platformio.org/page/projectconf.html
[common]
version = "1.5.3"
version = "1.5.6"
to_old_version = "1.5.0"
##
@@ -18,6 +18,7 @@ platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
#monitor_port = /dev/cu.usbmodem01
lib_deps =
tzapu/WiFiManager @ ^2.0.17
@@ -51,6 +52,7 @@ build_flags =
-mtext-section-literals
-DVERSION=\"${common.version}\"
-DTOOLDVERSION=\"${common.to_old_version}\"
#-DENABLE_HEAP_DEBUGGING
-DASYNCWEBSERVER_REGEX
#-DCORE_DEBUG_LEVEL=3
-DCONFIG_ARDUHAL_LOG_COLORS=1

View File

@@ -2,6 +2,8 @@
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include "commonFS.h"
#include <Preferences.h>
#include "debug.h"
volatile spoolmanApiStateType spoolmanApiState = API_INIT;
//bool spoolman_connected = false;
@@ -11,6 +13,7 @@ String octoUrl = "";
String octoToken = "";
struct SendToApiParams {
SpoolmanApiRequestType requestType;
String httpType;
String spoolsUrl;
String updatePayload;
@@ -86,10 +89,13 @@ JsonDocument fetchSingleSpoolInfo(int spoolId) {
}
void sendToApi(void *parameter) {
HEAP_DEBUG_MESSAGE("sendToApi begin");
spoolmanApiState = API_TRANSMITTING;
SendToApiParams* params = (SendToApiParams*)parameter;
// Extrahiere die Werte
SpoolmanApiRequestType requestType = params->requestType;
String httpType = params->httpType;
String spoolsUrl = params->spoolsUrl;
String updatePayload = params->updatePayload;
@@ -118,16 +124,19 @@ void sendToApi(void *parameter) {
Serial.print("Fehler beim Parsen der JSON-Antwort: ");
Serial.println(error.c_str());
} else {
if (httpType == "PUT") {
if (requestType == API_REQUEST_SPOOL_WEIGHT_UPDATE) {
uint16_t remaining_weight = doc["remaining_weight"].as<float>();
Serial.print("Aktuelles Gewicht: ");
Serial.println(remaining_weight);
oledShowMessage("Remaining: " + String(remaining_weight) + "g");
}
else if ( requestType == API_REQUEST_SPOOL_LOCATION_UPDATE) {
oledShowMessage("Location updated!");
}
vTaskDelay(3000 / portTICK_PERIOD_MS);
doc.clear();
}
doc.clear();
} else {
Serial.println("Fehler beim Senden an Spoolman! HTTP Code: " + String(httpCode));
@@ -140,8 +149,9 @@ void sendToApi(void *parameter) {
// Speicher freigeben
delete params;
vTaskDelete(NULL);
HEAP_DEBUG_MESSAGE("sendToApi end");
spoolmanApiState = API_IDLE;
vTaskDelete(NULL);
}
bool updateSpoolTagId(String uidString, const char* payload) {
@@ -164,6 +174,8 @@ bool updateSpoolTagId(String uidString, const char* payload) {
Serial.print("Update Spule mit URL: ");
Serial.println(spoolsUrl);
doc.clear();
// Update Payload erstellen
JsonDocument updateDoc;
updateDoc["extra"]["nfc_id"] = "\""+uidString+"\"";
@@ -178,6 +190,7 @@ bool updateSpoolTagId(String uidString, const char* payload) {
Serial.println("Fehler: Kann Speicher für Task-Parameter nicht allokieren.");
return false;
}
params->requestType = API_REQUEST_SPOOL_TAG_ID_UPDATE;
params->httpType = "PATCH";
params->spoolsUrl = spoolsUrl;
params->updatePayload = updatePayload;
@@ -201,6 +214,7 @@ bool updateSpoolTagId(String uidString, const char* payload) {
}
uint8_t updateSpoolWeight(String spoolId, uint16_t weight) {
HEAP_DEBUG_MESSAGE("updateSpoolWeight begin");
String spoolsUrl = spoolmanUrl + apiUrl + "/spool/" + spoolId + "/measure";
Serial.print("Update Spule mit URL: ");
Serial.println(spoolsUrl);
@@ -219,6 +233,7 @@ uint8_t updateSpoolWeight(String spoolId, uint16_t weight) {
Serial.println("Fehler: Kann Speicher für Task-Parameter nicht allokieren.");
return 0;
}
params->requestType = API_REQUEST_SPOOL_WEIGHT_UPDATE;
params->httpType = "PUT";
params->spoolsUrl = spoolsUrl;
params->updatePayload = updatePayload;
@@ -234,10 +249,53 @@ uint8_t updateSpoolWeight(String spoolId, uint16_t weight) {
);
updateDoc.clear();
HEAP_DEBUG_MESSAGE("updateSpoolWeight end");
return 1;
}
uint8_t updateSpoolLocation(String spoolId, String location){
HEAP_DEBUG_MESSAGE("updateSpoolLocation begin");
String spoolsUrl = spoolmanUrl + apiUrl + "/spool/" + spoolId;
Serial.print("Update Spule mit URL: ");
Serial.println(spoolsUrl);
// Update Payload erstellen
JsonDocument updateDoc;
updateDoc["location"] = location;
String updatePayload;
serializeJson(updateDoc, updatePayload);
Serial.print("Update Payload: ");
Serial.println(updatePayload);
SendToApiParams* params = new SendToApiParams();
if (params == nullptr) {
Serial.println("Fehler: Kann Speicher für Task-Parameter nicht allokieren.");
return 0;
}
params->requestType = API_REQUEST_SPOOL_LOCATION_UPDATE;
params->httpType = "PATCH";
params->spoolsUrl = spoolsUrl;
params->updatePayload = updatePayload;
// Erstelle die Task
BaseType_t result = xTaskCreate(
sendToApi, // Task-Funktion
"SendToApiTask", // Task-Name
6144, // Stackgröße in Bytes
(void*)params, // Parameter
0, // Priorität
NULL // Task-Handle (nicht benötigt)
);
updateDoc.clear();
HEAP_DEBUG_MESSAGE("updateSpoolLocation end");
return 1;
}
bool updateSpoolOcto(int spoolId) {
String spoolsUrl = octoUrl + "/plugin/Spoolman/selectSpool";
Serial.print("Update Spule in Octoprint mit URL: ");
@@ -257,6 +315,7 @@ bool updateSpoolOcto(int spoolId) {
Serial.println("Fehler: Kann Speicher für Task-Parameter nicht allokieren.");
return false;
}
params->requestType = API_REQUEST_OCTO_SPOOL_UPDATE;
params->httpType = "POST";
params->spoolsUrl = spoolsUrl;
params->updatePayload = updatePayload;
@@ -298,6 +357,10 @@ bool updateSpoolBambuData(String payload) {
String updatePayload;
serializeJson(updateDoc, updatePayload);
doc.clear();
updateDoc.clear();
Serial.print("Update Payload: ");
Serial.println(updatePayload);
@@ -306,6 +369,7 @@ bool updateSpoolBambuData(String payload) {
Serial.println("Fehler: Kann Speicher für Task-Parameter nicht allokieren.");
return false;
}
params->requestType = API_REQUEST_BAMBU_UPDATE;
params->httpType = "PATCH";
params->spoolsUrl = spoolsUrl;
params->updatePayload = updatePayload;
@@ -463,6 +527,7 @@ bool checkSpoolmanExtraFields() {
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
doc.clear();
}
}
@@ -509,48 +574,48 @@ bool checkSpoolmanInstance(const String& url) {
oledShowTopRow();
return strcmp(status, "healthy") == 0;
}
doc.clear();
}
} else {
Serial.println("Error contacting spoolman instance! HTTP Code: " + String(httpCode));
}
http.end();
return false;
}
bool saveSpoolmanUrl(const String& url, bool octoOn, const String& octoWh, const String& octoTk) {
if (!checkSpoolmanInstance(url)) return false;
bool saveSpoolmanUrl(const String& url, bool octoOn, const String& octo_url, const String& octoTk) {
Preferences preferences;
preferences.begin(NVS_NAMESPACE_API, false); // false = readwrite
preferences.putString(NVS_KEY_SPOOLMAN_URL, url);
preferences.putBool(NVS_KEY_OCTOPRINT_ENABLED, octoOn);
preferences.putString(NVS_KEY_OCTOPRINT_URL, octo_url);
preferences.putString(NVS_KEY_OCTOPRINT_TOKEN, octoTk);
preferences.end();
JsonDocument doc;
doc["url"] = url;
doc["octoEnabled"] = octoOn;
doc["octoUrl"] = octoWh;
doc["octoToken"] = octoTk;
Serial.print("Speichere Spoolman Data in Datei: ");
Serial.println(doc.as<String>());
if (!saveJsonValue("/spoolman_url.json", doc)) {
Serial.println("Fehler beim Speichern der Spoolman-URL.");
return false;
}
//TBD: This could be handled nicer in the future
spoolmanUrl = url;
octoEnabled = octoOn;
octoUrl = octoWh;
octoUrl = octo_url;
octoToken = octoTk;
doc.clear();
return true;
}
String loadSpoolmanUrl() {
JsonDocument doc;
if (loadJsonValue("/spoolman_url.json", doc) && doc["url"].is<String>()) {
octoEnabled = (doc["octoEnabled"].is<bool>()) ? doc["octoEnabled"].as<bool>() : false;
if (octoEnabled && doc["octoToken"].is<String>() && doc["octoUrl"].is<String>())
{
octoUrl = doc["octoUrl"].as<String>();
octoToken = doc["octoToken"].as<String>();
}
return doc["url"].as<String>();
Preferences preferences;
preferences.begin(NVS_NAMESPACE_API, true);
String spoolmanUrl = preferences.getString(NVS_KEY_SPOOLMAN_URL, "");
octoEnabled = preferences.getBool(NVS_KEY_OCTOPRINT_ENABLED, false);
if(octoEnabled)
{
octoUrl = preferences.getString(NVS_KEY_OCTOPRINT_URL, "");
octoToken = preferences.getString(NVS_KEY_OCTOPRINT_TOKEN, "");
}
Serial.println("Keine gültige Spoolman-URL gefunden.");
return "";
preferences.end();
return spoolmanUrl;
}
bool initSpoolman() {

View File

@@ -12,6 +12,14 @@ typedef enum {
API_TRANSMITTING
} spoolmanApiStateType;
typedef enum {
API_REQUEST_OCTO_SPOOL_UPDATE,
API_REQUEST_BAMBU_UPDATE,
API_REQUEST_SPOOL_TAG_ID_UPDATE,
API_REQUEST_SPOOL_WEIGHT_UPDATE,
API_REQUEST_SPOOL_LOCATION_UPDATE
} SpoolmanApiRequestType;
extern volatile spoolmanApiStateType spoolmanApiState;
extern bool spoolman_connected;
extern String spoolmanUrl;
@@ -26,6 +34,7 @@ bool checkSpoolmanExtraFields(); // Neue Funktion zum Überprüfen der Extrafeld
JsonDocument fetchSingleSpoolInfo(int spoolId); // API-Funktion für die Webseite
bool updateSpoolTagId(String uidString, const char* payload); // Neue Funktion zum Aktualisieren eines Spools
uint8_t updateSpoolWeight(String spoolId, uint16_t weight); // Neue Funktion zum Aktualisieren des Gewichts
uint8_t updateSpoolLocation(String spoolId, String location);
bool initSpoolman(); // Neue Funktion zum Initialisieren von Spoolman
bool updateSpoolBambuData(String payload); // Neue Funktion zum Aktualisieren der Bambu-Daten
bool updateSpoolOcto(int spoolId); // Neue Funktion zum Aktualisieren der Octo-Daten

View File

@@ -10,6 +10,7 @@
#include "esp_task_wdt.h"
#include "config.h"
#include "display.h"
#include <Preferences.h>
WiFiClient espClient;
SSLClient sslClient(&espClient);
@@ -17,22 +18,13 @@ PubSubClient client(sslClient);
TaskHandle_t BambuMqttTask;
String topic = "";
//String request_topic = "";
const char* bambu_username = "bblp";
const char* bambu_ip = nullptr;
const char* bambu_accesscode = nullptr;
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;
int autoSetToBambuSpoolId = 0;
BambuCredentials bambuCredentials;
// Globale Variablen für AMS-Daten
int ams_count = 0;
String amsJsonData; // Speichert das fertige JSON für WebSocket-Clients
@@ -43,18 +35,22 @@ bool removeBambuCredentials() {
vTaskDelete(BambuMqttTask);
}
if (!removeJsonValue("/bambu_credentials.json")) {
Serial.println("Fehler beim Löschen der Bambu-Credentials.");
return false;
}
Preferences preferences;
preferences.begin(NVS_NAMESPACE_BAMBU, false); // false = readwrite
preferences.remove(NVS_KEY_BAMBU_IP);
preferences.remove(NVS_KEY_BAMBU_SERIAL);
preferences.remove(NVS_KEY_BAMBU_ACCESSCODE);
preferences.remove(NVS_KEY_BAMBU_AUTOSEND_ENABLE);
preferences.remove(NVS_KEY_BAMBU_AUTOSEND_TIME);
preferences.end();
// 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;
bambuCredentials.ip = "";
bambuCredentials.serial = "";
bambuCredentials.accesscode = "";
bambuCredentials.autosend_enable = false;
bambuCredentials.autosend_time = BAMBU_DEFAULT_AUTOSEND_TIME;
autoSetToBambuSpoolId = 0;
ams_count = 0;
amsJsonData = "";
@@ -68,25 +64,21 @@ bool saveBambuCredentials(const String& ip, const String& serialnr, const String
if (BambuMqttTask) {
vTaskDelete(BambuMqttTask);
}
JsonDocument doc;
doc["bambu_ip"] = ip;
doc["bambu_accesscode"] = accesscode;
doc["bambu_serialnr"] = serialnr;
doc["autoSendToBambu"] = autoSend;
doc["autoSendTime"] = (autoSendTime != "") ? autoSendTime.toInt() : autoSetBambuAmsCounter;
if (!saveJsonValue("/bambu_credentials.json", doc)) {
Serial.println("Fehler beim Speichern der Bambu-Credentials.");
return false;
}
bambuCredentials.ip = ip.c_str();
bambuCredentials.serial = serialnr.c_str();
bambuCredentials.accesscode = accesscode.c_str();
bambuCredentials.autosend_enable = autoSend;
bambuCredentials.autosend_time = autoSendTime.toInt();
// Dynamische Speicherallokation für die globalen Pointer
bambu_ip = ip.c_str();
bambu_accesscode = accesscode.c_str();
bambu_serialnr = serialnr.c_str();
autoSendToBambu = autoSend;
autoSetBambuAmsCounter = autoSendTime.toInt();
Preferences preferences;
preferences.begin(NVS_NAMESPACE_BAMBU, false); // false = readwrite
preferences.putString(NVS_KEY_BAMBU_IP, bambuCredentials.ip);
preferences.putString(NVS_KEY_BAMBU_SERIAL, bambuCredentials.serial);
preferences.putString(NVS_KEY_BAMBU_ACCESSCODE, bambuCredentials.accesscode);
preferences.putBool(NVS_KEY_BAMBU_AUTOSEND_ENABLE, bambuCredentials.autosend_enable);
preferences.putInt(NVS_KEY_BAMBU_AUTOSEND_TIME, bambuCredentials.autosend_time);
preferences.end();
vTaskDelay(100 / portTICK_PERIOD_MS);
if (!setupMqtt()) return false;
@@ -95,35 +87,36 @@ bool saveBambuCredentials(const String& ip, const String& serialnr, const String
}
bool loadBambuCredentials() {
JsonDocument doc;
if (loadJsonValue("/bambu_credentials.json", doc) && doc["bambu_ip"].is<String>()) {
// Temporäre Strings für die Werte
String ip = doc["bambu_ip"].as<String>();
String code = doc["bambu_accesscode"].as<String>();
String serial = doc["bambu_serialnr"].as<String>();
Preferences preferences;
preferences.begin(NVS_NAMESPACE_BAMBU, true);
String ip = preferences.getString(NVS_KEY_BAMBU_IP, "");
String serial = preferences.getString(NVS_KEY_BAMBU_SERIAL, "");
String code = preferences.getString(NVS_KEY_BAMBU_ACCESSCODE, "");
bool autosendEnable = preferences.getBool(NVS_KEY_BAMBU_AUTOSEND_ENABLE, false);
int autosendTime = preferences.getInt(NVS_KEY_BAMBU_AUTOSEND_TIME, BAMBU_DEFAULT_AUTOSEND_TIME);
preferences.end();
g_bambu_ip = ip;
g_bambu_accesscode = code;
g_bambu_serialnr = serial;
if(ip != ""){
bambuCredentials.ip = ip.c_str();
bambuCredentials.serial = serial.c_str();
bambuCredentials.accesscode = code.c_str();
bambuCredentials.autosend_enable = autosendEnable;
bambuCredentials.autosend_time = autosendTime;
if (doc["autoSendToBambu"].is<bool>()) autoSendToBambu = doc["autoSendToBambu"].as<bool>();
if (doc["autoSendTime"].is<int>()) autoSetBambuAmsCounter = doc["autoSendTime"].as<int>();
Serial.println("credentials loaded loadCredentials!");
Serial.println(bambuCredentials.ip);
Serial.println(bambuCredentials.serial);
Serial.println(bambuCredentials.accesscode);
Serial.println(String(bambuCredentials.autosend_enable));
Serial.println(String(bambuCredentials.autosend_time));
ip.trim();
code.trim();
serial.trim();
// Dynamische Speicherallokation für die globalen Pointer
bambu_ip = g_bambu_ip.c_str();
bambu_accesscode = g_bambu_accesscode.c_str();
bambu_serialnr = g_bambu_serialnr.c_str();
topic = "device/" + String(bambu_serialnr);
//request_topic = "device/" + String(bambu_serialnr) + "/request";
return true;
}
Serial.println("Keine gültigen Bambu-Credentials gefunden.");
return false;
else
{
Serial.println("Keine gültigen Bambu-Credentials gefunden.");
return false;
}
}
struct FilamentResult {
@@ -226,7 +219,7 @@ FilamentResult findFilamentIdx(String brand, String type) {
bool sendMqttMessage(const String& payload) {
Serial.println("Sending MQTT message");
Serial.println(payload);
if (client.publish((String(topic) + "/request").c_str(), payload.c_str()))
if (client.publish(("device/"+bambuCredentials.serial+"/request").c_str(), payload.c_str()))
{
return true;
}
@@ -499,7 +492,7 @@ void mqtt_callback(char* topic, byte* payload, unsigned int length) {
trayObj["cali_idx"].as<String>() != ams_data[storedIndex].trays[j].cali_idx) {
hasChanges = true;
if (autoSendToBambu && autoSetToBambuSpoolId > 0 && hasChanges)
if (bambuCredentials.autosend_enable && autoSetToBambuSpoolId > 0 && hasChanges)
{
autoSetSpool(autoSetToBambuSpoolId, ams_data[storedIndex].trays[j].id);
}
@@ -523,7 +516,7 @@ void mqtt_callback(char* topic, byte* payload, unsigned int length) {
(vtTray["tray_type"].as<String>() != "" && vtTray["cali_idx"].as<String>() != ams_data[i].trays[0].cali_idx)) {
hasChanges = true;
if (autoSendToBambu && autoSetToBambuSpoolId > 0 && hasChanges)
if (bambuCredentials.autosend_enable && autoSetToBambuSpoolId > 0 && hasChanges)
{
autoSetSpool(autoSetToBambuSpoolId, 254);
}
@@ -580,11 +573,11 @@ void reconnect() {
oledShowTopRow();
// Attempt to connect
String clientId = String(bambu_serialnr) + "_" + String(random(0, 100));
if (client.connect(clientId.c_str(), bambu_username, bambu_accesscode)) {
String clientId = bambuCredentials.serial + "_" + String(random(0, 100));
if (client.connect(clientId.c_str(), BAMBU_USERNAME, bambuCredentials.accesscode.c_str())) {
Serial.println("MQTT re/connected");
client.subscribe((String(topic) + "/report").c_str());
client.subscribe(("device/"+bambuCredentials.serial+"/report").c_str());
bambu_connected = true;
oledShowTopRow();
} else {
@@ -630,28 +623,23 @@ void mqtt_loop(void * parameter) {
bool setupMqtt() {
// Wenn Bambu Daten vorhanden
bool success = loadBambuCredentials();
//bool success = loadBambuCredentials();
if (!success) {
bambuDisabled = true;
return false;
}
if (success && bambu_ip != "" && bambu_accesscode != "" && bambu_serialnr != "")
if (bambuCredentials.ip != "" && bambuCredentials.accesscode != "" && bambuCredentials.serial != "")
{
bambuDisabled = false;
sslClient.setCACert(root_ca);
sslClient.setInsecure();
client.setServer(bambu_ip, 8883);
client.setServer(bambuCredentials.ip.c_str(), 8883);
// Verbinden mit dem MQTT-Server
bool connected = true;
String clientId = String(bambu_serialnr) + "_" + String(random(0, 100));
if (client.connect(clientId.c_str(), bambu_username, bambu_accesscode))
String clientId = String(bambuCredentials.serial) + "_" + String(random(0, 100));
if (client.connect(bambuCredentials.ip.c_str(), BAMBU_USERNAME, bambuCredentials.accesscode.c_str()))
{
client.setCallback(mqtt_callback);
client.setBufferSize(15488);
client.subscribe((String(topic) + "/report").c_str());
client.subscribe(("device/"+bambuCredentials.serial+"/report").c_str());
Serial.println("MQTT-Client initialisiert");
oledShowMessage("Bambu Connected");

View File

@@ -16,6 +16,14 @@ struct TrayData {
String cali_idx;
};
struct BambuCredentials {
String ip;
String serial;
String accesscode;
bool autosend_enable;
int autosend_time;
};
#define MAX_AMS 17 // 16 normale AMS + 1 externe Spule
extern String amsJsonData; // Für die vorbereiteten JSON-Daten
@@ -28,9 +36,10 @@ extern bool bambu_connected;
extern int ams_count;
extern AMSData ams_data[MAX_AMS];
extern bool autoSendToBambu;
//extern bool autoSendToBambu;
extern int autoSetToBambuSpoolId;
extern bool bambuDisabled;
extern BambuCredentials bambuCredentials;
bool removeBambuCredentials();
bool loadBambuCredentials();

View File

@@ -46,8 +46,6 @@ const uint8_t webserverPort = 80;
const char* apiUrl = "/api/v1";
// ***** API
// ***** Bambu Auto Set Spool
uint8_t autoSetBambuAmsCounter = 60;
// ***** Bambu Auto Set Spool
// ***** Task Prios

View File

@@ -3,6 +3,29 @@
#include <Arduino.h>
#define BAMBU_DEFAULT_AUTOSEND_TIME 60
#define NVS_NAMESPACE_API "api"
#define NVS_KEY_SPOOLMAN_URL "spoolmanUrl"
#define NVS_KEY_OCTOPRINT_ENABLED "octoEnabled"
#define NVS_KEY_OCTOPRINT_URL "octoUrl"
#define NVS_KEY_OCTOPRINT_TOKEN "octoToken"
#define NVS_NAMESPACE_BAMBU "bambu"
#define NVS_KEY_BAMBU_IP "bambuIp"
#define NVS_KEY_BAMBU_ACCESSCODE "bambuCode"
#define NVS_KEY_BAMBU_SERIAL "bambuSerial"
#define NVS_KEY_BAMBU_AUTOSEND_ENABLE "autosendEnable"
#define NVS_KEY_BAMBU_AUTOSEND_TIME "autosendTime"
#define NVS_NAMESPACE_SCALE "scale"
#define NVS_KEY_CALIBRATION "cal_value"
#define NVS_KEY_AUTOTARE "auto_tare"
#define BAMBU_USERNAME "bblp"
extern const uint8_t PN532_IRQ;
extern const uint8_t PN532_RESET;
@@ -25,7 +48,7 @@ extern const uint8_t OLED_DATA_END;
extern const char* apiUrl;
extern const uint8_t webserverPort;
extern uint8_t autoSetBambuAmsCounter;
extern const unsigned char wifi_on[];
extern const unsigned char wifi_off[];

12
src/debug.h Normal file
View File

@@ -0,0 +1,12 @@
#include <Arduino.h>
#ifdef ENABLE_HEAP_DEBUGGING
#define HEAP_DEBUG_MESSAGE(location) printHeapDebugData(location);
#else
#define HEAP_DEBUG_MESSAGE(location)
#endif
inline void printHeapDebugData(String location){
Serial.println("Heap: " + String(ESP.getMinFreeHeap()/1024) + "\t" + String(ESP.getFreeHeap()/1024) + "\t" + String(ESP.getMaxAllocHeap()/1024) + "\t" + location);
}

View File

@@ -119,7 +119,7 @@ void loop() {
}
// Wenn Bambu auto set Spool aktiv
if (autoSendToBambu && autoSetToBambuSpoolId > 0)
if (bambuCredentials.autosend_enable && autoSetToBambuSpoolId > 0)
{
if (!bambuDisabled && !bambu_connected)
{
@@ -131,10 +131,10 @@ void loop() {
if (nfcReaderState == NFC_IDLE)
{
lastAutoSetBambuAmsTime = currentMillis;
oledShowMessage("Auto Set " + String(autoSetBambuAmsCounter - autoAmsCounter) + "s");
oledShowMessage("Auto Set " + String(bambuCredentials.autosend_time - autoAmsCounter) + "s");
autoAmsCounter++;
if (autoAmsCounter >= autoSetBambuAmsCounter)
if (autoAmsCounter >= bambuCredentials.autosend_time)
{
autoSetToBambuSpoolId = 0;
autoAmsCounter = 0;
@@ -162,7 +162,7 @@ void loop() {
// Ausgabe der Waage auf Display
if(pauseMainTask == 0)
{
if (mainTaskWasPaused || (weight != lastWeight && nfcReaderState == NFC_IDLE && (!autoSendToBambu || autoSetToBambuSpoolId == 0)))
if (mainTaskWasPaused || (weight != lastWeight && nfcReaderState == NFC_IDLE && (!bambuCredentials.autosend_enable || autoSetToBambuSpoolId == 0)))
{
(weight < 2) ? ((weight < -2) ? oledShowMessage("!! -0") : oledShowWeight(0)) : oledShowWeight(weight);
}
@@ -212,14 +212,14 @@ 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 && nfcReaderState == NFC_READ_SUCCESS) {
if (activeSpoolId != "" && weigthCouterToApi > 3 && weightSend == 0 && nfcReaderState == NFC_READ_SUCCESS) {
oledShowIcon("loading");
if (updateSpoolWeight(spoolId, weight))
if (updateSpoolWeight(activeSpoolId, weight))
{
oledShowIcon("success");
vTaskDelay(2000 / portTICK_PERIOD_MS);
weightSend = 1;
autoSetToBambuSpoolId = spoolId.toInt();
autoSetToBambuSpoolId = activeSpoolId.toInt();
if (octoEnabled)
{

View File

@@ -7,6 +7,7 @@
#include "api.h"
#include "esp_task_wdt.h"
#include "scale.h"
#include "bambu.h"
//Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS);
Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);
@@ -14,7 +15,8 @@ Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);
TaskHandle_t RfidReaderTask;
JsonDocument rfidData;
String spoolId = "";
String activeSpoolId = "";
String lastSpoolId = "";
String nfcJsonData = "";
volatile bool pauseBambuMqttTask = false;
@@ -64,6 +66,8 @@ void payloadToJson(uint8_t *data) {
Serial.print("deserializeJson() failed: ");
Serial.println(error.f_str());
}
doc.clear();
} else {
Serial.println("Kein gültiger JSON-Inhalt gefunden oder fehlerhafte Formatierung.");
//writeJsonToTag("{\"version\":\"1.0\",\"protocol\":\"NFC\",\"color_hex\":\"#FFFFFF\",\"type\":\"Example\",\"min_temp\":10,\"max_temp\":30,\"brand\":\"BrandName\"}");
@@ -218,20 +222,37 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage) {
// Sende die aktualisierten AMS-Daten an alle WebSocket-Clients
Serial.println("JSON-Dokument erfolgreich verarbeitet");
Serial.println(doc.as<String>());
if (doc["sm_id"] != "")
if (doc["sm_id"].is<String>() && doc["sm_id"] != "")
{
Serial.println("SPOOL-ID gefunden: " + doc["sm_id"].as<String>());
spoolId = doc["sm_id"].as<String>();
}
activeSpoolId = doc["sm_id"].as<String>();
lastSpoolId = activeSpoolId;
}
else if(doc["location"].is<String>() && doc["location"] != "")
{
Serial.println("Location Tag found!");
String location = doc["location"].as<String>();
if(lastSpoolId != ""){
updateSpoolLocation(lastSpoolId, location);
}
else
{
Serial.println("Location update tag scanned without scanning spool before!");
oledShowMessage("No spool scanned before!");
}
}
else
{
Serial.println("Keine SPOOL-ID gefunden.");
spoolId = "";
activeSpoolId = "";
oledShowMessage("Unknown Spool");
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
}
doc.clear();
return true;
}
@@ -432,8 +453,9 @@ void scanRfidTask(void * parameter) {
nfcReaderState = NFC_IDLE;
//uidString = "";
nfcJsonData = "";
activeSpoolId = "";
Serial.println("Tag entfernt");
if (!autoSendToBambu) oledShowWeight(weight);
if (!bambuCredentials.autosend_enable) oledShowWeight(weight);
}
// aktualisieren der Website wenn sich der Status ändert

View File

@@ -19,7 +19,8 @@ void startWriteJsonToTag(const char* payload);
extern TaskHandle_t RfidReaderTask;
extern String nfcJsonData;
extern String spoolId;
extern String activeSpoolId;
extern String lastSpoolId;
extern volatile nfcReaderStateType nfcReaderState;
extern volatile bool pauseBambuMqttTask;

View File

@@ -18,11 +18,6 @@ uint8_t scale_tare_counter = 0;
bool scaleTareRequest = false;
uint8_t pauseMainTask = 0;
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 #####
@@ -32,7 +27,8 @@ uint8_t setAutoTare(bool autoTareValue) {
autoTare = autoTareValue;
// Speichern mit NVS
preferences.begin(NVS_NAMESPACE, false); // false = readwrite
Preferences preferences;
preferences.begin(NVS_NAMESPACE_SCALE, false); // false = readwrite
preferences.putBool(NVS_KEY_AUTOTARE, autoTare);
preferences.end();
@@ -74,7 +70,11 @@ void scale_loop(void * parameter) {
scaleTareRequest = false;
}
weight = round(scale.get_units());
// Only update weight if median changed more than 1
int16_t newWeight = round(scale.get_units());
if(abs(weight-newWeight) > 1){
weight = newWeight;
}
}
vTaskDelay(pdMS_TO_TICKS(100));
@@ -86,7 +86,8 @@ void start_scale(bool touchSensorConnected) {
float calibrationValue;
// NVS lesen
preferences.begin(NVS_NAMESPACE, true); // true = readonly
Preferences preferences;
preferences.begin(NVS_NAMESPACE_SCALE, true); // true = readonly
calibrationValue = preferences.getFloat(NVS_KEY_CALIBRATION, defaultScaleCalibrationValue);
// auto Tare
@@ -193,12 +194,13 @@ uint8_t calibrate_scale() {
Serial.println(newCalibrationValue);
// Speichern mit NVS
preferences.begin(NVS_NAMESPACE, false); // false = readwrite
Preferences preferences;
preferences.begin(NVS_NAMESPACE_SCALE, false); // false = readwrite
preferences.putFloat(NVS_KEY_CALIBRATION, newCalibrationValue);
preferences.end();
// Verifizieren
preferences.begin(NVS_NAMESPACE, true);
preferences.begin(NVS_NAMESPACE_SCALE, true);
float verifyValue = preferences.getFloat(NVS_KEY_CALIBRATION, 0);
preferences.end();

View File

@@ -10,6 +10,9 @@
#include <Update.h>
#include "display.h"
#include "ota.h"
#include "config.h"
#include "debug.h"
#ifndef VERSION
#define VERSION "1.1.0"
@@ -26,6 +29,7 @@ nfcReaderStateType lastnfcReaderState = NFC_IDLE;
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
HEAP_DEBUG_MESSAGE("onWsEvent begin");
if (type == WS_EVT_CONNECT) {
Serial.println("Neuer Client verbunden!");
// Sende die AMS-Daten an den neuen Client
@@ -33,6 +37,10 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
sendNfcData(client);
foundNfcTag(client, 0);
sendWriteResult(client, 3);
// Clean up dead connections
(*server).cleanupClients();
Serial.println("Currently connected number of clients: " + String((*server).getClients().size()));
} else if (type == WS_EVT_DISCONNECT) {
Serial.println("Client getrennt.");
} else if (type == WS_EVT_ERROR) {
@@ -113,7 +121,9 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
else {
Serial.println("Unbekannter WebSocket-Typ: " + doc["type"].as<String>());
}
doc.clear();
}
HEAP_DEBUG_MESSAGE("onWsEvent end");
}
// Funktion zum Laden und Ersetzen des Headers in einer HTML-Datei
@@ -195,6 +205,9 @@ void setupWebserver(AsyncWebServer &server) {
Serial.print("Geladene Spoolman-URL: ");
Serial.println(spoolmanUrl);
// Load Bamb credentials:
loadBambuCredentials();
// Route für about
server.on("/about", HTTP_GET, [](AsyncWebServerRequest *request){
Serial.println("Anfrage für /about erhalten");
@@ -254,31 +267,13 @@ void setupWebserver(AsyncWebServer &server) {
html.replace("{{spoolmanOctoUrl}}", (octoUrl != "") ? octoUrl : "");
html.replace("{{spoolmanOctoToken}}", (octoToken != "") ? octoToken : "");
JsonDocument doc;
if (loadJsonValue("/bambu_credentials.json", doc) && doc["bambu_ip"].is<String>())
{
String bambuIp = doc["bambu_ip"].as<String>();
String bambuSerial = doc["bambu_serialnr"].as<String>();
String bambuCode = doc["bambu_accesscode"].as<String>();
autoSendToBambu = doc["autoSendToBambu"].as<bool>();
bambuIp.trim();
bambuSerial.trim();
bambuCode.trim();
html.replace("{{bambuIp}}", bambuCredentials.ip);
html.replace("{{bambuSerial}}", bambuCredentials.serial);
html.replace("{{bambuCode}}", bambuCredentials.accesscode ? bambuCredentials.accesscode : "");
html.replace("{{autoSendToBambu}}", bambuCredentials.autosend_enable ? "checked" : "");
html.replace("{{autoSendTime}}", (bambuCredentials.autosend_time != 0) ? String(bambuCredentials.autosend_time) : String(BAMBU_DEFAULT_AUTOSEND_TIME));
html.replace("{{bambuIp}}", bambuIp ? bambuIp : "");
html.replace("{{bambuSerial}}", bambuSerial ? bambuSerial : "");
html.replace("{{bambuCode}}", bambuCode ? bambuCode : "");
html.replace("{{autoSendToBambu}}", autoSendToBambu ? "checked" : "");
html.replace("{{autoSendTime}}", String(autoSetBambuAmsCounter));
}
else
{
html.replace("{{bambuIp}}", "");
html.replace("{{bambuSerial}}", "");
html.replace("{{bambuCode}}", "");
html.replace("{{autoSendToBambu}}", "");
html.replace("{{autoSendTime}}", String(autoSetBambuAmsCounter));
}
doc.clear();
request->send(200, "text/html", html);
});