Compare commits
49 Commits
Author | SHA1 | Date | |
---|---|---|---|
012f91851e | |||
9ed3c70c01 | |||
e23f3a2151 | |||
f73306f0b9 | |||
a450d4bd1a | |||
d48d994c00 | |||
32bb85f897 | |||
e9d32ee060 | |||
aba28422bd | |||
4a55620d39 | |||
7b18266534 | |||
d81acb2b61 | |||
8c7fc159d3 | |||
476d3e82e2 | |||
3c294a135f | |||
bb751b6289 | |||
7fd01bd1b9 | |||
fad84e12c8 | |||
696efc4d79 | |||
29868e7101 | |||
823db6157c | |||
458cc4eaf2 | |||
83d14b32d1 | |||
2bf7c9fb7d | |||
|
ac8adca84d | ||
|
c701149c64 | ||
07a919b6ba | |||
8618b90e33 | |||
57723b5354 | |||
d2be752175 | |||
97a050ace8 | |||
367e692c74 | |||
926a21249b | |||
2635c19667 | |||
|
6cc4efca0a | ||
1484a6b0da | |||
b5f0472af4 | |||
95c1bc823c | |||
491ba7f526 | |||
56d7d8596c | |||
1044e91a0a | |||
e459b53472 | |||
024056cb7d | |||
e040a736b0 | |||
72b6b349c6 | |||
190e952ec4 | |||
89620a7f00 | |||
536950eeb3 | |||
|
fe4d2d7479 |
99
CHANGELOG.md
99
CHANGELOG.md
@ -1,5 +1,104 @@
|
||||
# Changelog
|
||||
|
||||
## [1.5.1] - 2025-03-30
|
||||
### Changed
|
||||
- update version to 1.5.1 and improve OTA update handling with task management
|
||||
|
||||
|
||||
## [1.4.14] - 2025-03-30
|
||||
### Added
|
||||
- add auto-tare functionality and update scale handling based on touch sensor connection
|
||||
|
||||
### Changed
|
||||
- update platformio.ini for version v1.4.14
|
||||
|
||||
|
||||
## [1.4.13] - 2025-03-30
|
||||
### Changed
|
||||
- update platformio.ini for version v1.4.13
|
||||
|
||||
### Fixed
|
||||
- update touch sensor connection logic to correctly identify connection status
|
||||
|
||||
|
||||
## [1.4.12] - 2025-03-30
|
||||
### Added
|
||||
- add touch sensor connection check and update logic
|
||||
|
||||
### Changed
|
||||
- update platformio.ini for version v1.4.12
|
||||
- update README files to clarify PN532 DIP switch settings
|
||||
|
||||
|
||||
## [1.4.11] - 2025-03-30
|
||||
### Added
|
||||
- Renamed states of NFC state machine and introduced new state machine for spoolman API
|
||||
|
||||
### Changed
|
||||
- update platformio.ini for version v1.4.11
|
||||
- Merge branch 'main' of github.com:ManuelW77/Filaman
|
||||
- Merge pull request #31 from janecker/nfc_rework
|
||||
- Introducing enum for handling the NFC state to improve code readability
|
||||
|
||||
|
||||
## [1.4.10] - 2025-03-30
|
||||
### Added
|
||||
- add manual tare functionality for scale
|
||||
- add debounce handling for TTP223 touch sensor
|
||||
- add TTP223 touch sensor support and wiring configuration
|
||||
|
||||
### Changed
|
||||
- update platformio.ini for version v1.4.10
|
||||
|
||||
### Fixed
|
||||
- update TTP223 pin configuration and adjust touch sensor logic
|
||||
|
||||
|
||||
## [1.4.9] - 2025-03-29
|
||||
### Changed
|
||||
- update platformio.ini for version v1.4.9
|
||||
|
||||
### Fixed
|
||||
- enhance HTTP method handling in sendToApi function
|
||||
|
||||
|
||||
## [1.4.8] - 2025-03-29
|
||||
### Changed
|
||||
- update platformio.ini for version v1.4.8
|
||||
- Merge pull request #30 from janecker/main
|
||||
- Merge branch 'testing' into main
|
||||
|
||||
### Fixed
|
||||
- improve HTTP client configuration and clear update documents after API calls
|
||||
- Fixes memory leak in HTTPClient by disabling connection reuse
|
||||
- update reload logic after removing and saving Bambu credentials for better cache handling
|
||||
|
||||
|
||||
## [1.4.7] - 2025-03-27
|
||||
### Added
|
||||
- add forced cache refresh after removing and saving Bambu credentials
|
||||
- add functionality to remove Bambu credentials and update API handling
|
||||
- add rfid_bambu.html and update bambu connection handling
|
||||
|
||||
### Changed
|
||||
- update platformio.ini for version v1.4.7
|
||||
- Merge branch 'testing'
|
||||
- update remove button for Bambu credentials with red background
|
||||
- Merge pull request #28 from tugsi/main
|
||||
|
||||
### Fixed
|
||||
- handle Bambu connection state by introducing bambuDisabled flag
|
||||
- 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
|
||||
|
||||
|
||||
## [1.4.6] - 2025-03-26
|
||||
### Changed
|
||||
- update platformio.ini for version v1.4.6
|
||||
|
||||
### Fixed
|
||||
- handle potential undefined value for tray_info_idx in handleSpoolIn function, by @tugsi
|
||||
|
||||
|
||||
## [1.4.5] - 2025-03-25
|
||||
### Changed
|
||||
- update platformio.ini for version v1.4.5
|
||||
|
31
README.de.md
31
README.de.md
@ -55,19 +55,22 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v)
|
||||
## Hardware-Anforderungen
|
||||
|
||||
### Komponenten
|
||||
- **ESP32 Entwicklungsboard:** Jede ESP32-Variante.
|
||||
[Amazon Link](https://amzn.eu/d/aXThslf)
|
||||
- **HX711 5kg Wägezellen-Verstärker:** Für Gewichtsmessung.
|
||||
[Amazon Link](https://amzn.eu/d/06A0DLb)
|
||||
- **OLED 0.96 Zoll I2C weiß/gelb Display:** 128x64 SSD1306.
|
||||
[Amazon Link](https://amzn.eu/d/0AuBp2c)
|
||||
- **PN532 NFC NXP RFID-Modul V3:** Für NFC-Tag-Operationen.
|
||||
[Amazon Link](https://amzn.eu/d/jfIuQXb)
|
||||
- **NFC Tags NTAG213 NTA215:** RFID Tag
|
||||
[Amazon Link](https://amzn.eu/d/9Z6mXc1)
|
||||
- **ESP32 Development Board:** Any ESP32 variant.
|
||||
[Amazon Link](https://amzn.to/3FHea6D)
|
||||
- **HX711 5kg Load Cell Amplifier:** For weight measurement.
|
||||
[Amazon Link](https://amzn.to/4ja1KTe)
|
||||
- **OLED 0.96 Zoll I2C white/yellow Display:** 128x64 SSD1306.
|
||||
[Amazon Link](https://amzn.to/445aaa9)
|
||||
- **PN532 NFC NXP RFID-Modul V3:** For NFC tag operations.
|
||||
[Amazon Link](https://amzn.to/4iO6CO4)
|
||||
- **NFC Tags NTAG213 NTAG215:** RFID Tag
|
||||
[Amazon Link](https://amzn.to/3E071xO)
|
||||
- **TTP223 Touch Sensor (optional):** For reTARE per Button/Touch
|
||||
[Amazon Link](https://amzn.to/4hTChMK)
|
||||
|
||||
### Pin-Konfiguration
|
||||
| Komponente | ESP32 Pin |
|
||||
|
||||
### Pin Konfiguration
|
||||
| Component | ESP32 Pin |
|
||||
|-------------------|-----------|
|
||||
| HX711 DOUT | 16 |
|
||||
| HX711 SCK | 17 |
|
||||
@ -77,8 +80,10 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v)
|
||||
| PN532 RESET | 33 |
|
||||
| PN532 SDA | 21 |
|
||||
| PN532 SCL | 22 |
|
||||
| TTP223 I/O | 25 |
|
||||
|
||||
**Achte darauf, dass am PN532 die DIP-Schalter auf I2C gestellt sind**
|
||||
**!! Achte darauf, dass am PN532 die DIP-Schalter auf I2C gestellt sind**
|
||||
**Nutze den 3V Pin vom ESP für den Touch Sensor**
|
||||
|
||||

|
||||
|
||||
|
16
README.md
16
README.md
@ -60,15 +60,17 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v)
|
||||
|
||||
### Components
|
||||
- **ESP32 Development Board:** Any ESP32 variant.
|
||||
[Amazon Link](https://amzn.eu/d/aXThslf)
|
||||
[Amazon Link](https://amzn.to/3FHea6D)
|
||||
- **HX711 5kg Load Cell Amplifier:** For weight measurement.
|
||||
[Amazon Link](https://amzn.eu/d/06A0DLb)
|
||||
[Amazon Link](https://amzn.to/4ja1KTe)
|
||||
- **OLED 0.96 Zoll I2C white/yellow Display:** 128x64 SSD1306.
|
||||
[Amazon Link](https://amzn.eu/d/0AuBp2c)
|
||||
[Amazon Link](https://amzn.to/445aaa9)
|
||||
- **PN532 NFC NXP RFID-Modul V3:** For NFC tag operations.
|
||||
[Amazon Link](https://amzn.eu/d/jfIuQXb)
|
||||
[Amazon Link](https://amzn.to/4iO6CO4)
|
||||
- **NFC Tags NTAG213 NTAG215:** RFID Tag
|
||||
[Amazon Link](https://amzn.eu/d/9Z6mXc1)
|
||||
[Amazon Link](https://amzn.to/3E071xO)
|
||||
- **TTP223 Touch Sensor (optional):** For reTARE per Button/Touch
|
||||
[Amazon Link](https://amzn.to/4hTChMK)
|
||||
|
||||
|
||||
### Pin Configuration
|
||||
@ -82,8 +84,10 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v)
|
||||
| PN532 RESET | 33 |
|
||||
| PN532 SDA | 21 |
|
||||
| PN532 SCL | 22 |
|
||||
| TTP223 I/O | 25 |
|
||||
|
||||
**Make sure that the DIP switches on the PN532 are set to I2C**
|
||||
**!! Make sure that the DIP switches on the PN532 are set to I2C**
|
||||
**Use the 3V pin from the ESP for the touch sensor**
|
||||
|
||||

|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
14
html/rfid.js
14
html/rfid.js
@ -11,7 +11,7 @@ let reconnectTimer = null;
|
||||
// WebSocket Funktionen
|
||||
function startHeartbeat() {
|
||||
if (heartbeatTimer) clearInterval(heartbeatTimer);
|
||||
|
||||
|
||||
heartbeatTimer = setInterval(() => {
|
||||
// Prüfe ob zu lange keine Antwort kam
|
||||
if (Date.now() - lastHeartbeatResponse > HEARTBEAT_TIMEOUT) {
|
||||
@ -29,7 +29,7 @@ function startHeartbeat() {
|
||||
updateConnectionStatus();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
// Sende Heartbeat
|
||||
socket.send(JSON.stringify({ type: 'heartbeat' }));
|
||||
@ -83,7 +83,7 @@ function initWebSocket() {
|
||||
isConnected = false;
|
||||
updateConnectionStatus();
|
||||
if (heartbeatTimer) clearInterval(heartbeatTimer);
|
||||
|
||||
|
||||
// Bei Fehler Verbindung schließen und neu aufbauen
|
||||
if (socket) {
|
||||
socket.close();
|
||||
@ -109,7 +109,7 @@ function initWebSocket() {
|
||||
const bambuDot = document.getElementById('bambuDot');
|
||||
const spoolmanDot = document.getElementById('spoolmanDot');
|
||||
const ramStatus = document.getElementById('ramStatus');
|
||||
|
||||
|
||||
if (bambuDot) {
|
||||
bambuDot.className = 'status-dot ' + (data.bambu_connected ? 'online' : 'offline');
|
||||
// Add click handler only when offline
|
||||
@ -208,7 +208,7 @@ document.addEventListener('spoolmanError', function(event) {
|
||||
showNotification(`Spoolman Error: ${event.detail.message}`, false);
|
||||
});
|
||||
|
||||
document.addEventListener('filamentSelected', function(event) {
|
||||
document.addEventListener('filamentSelected', function (event) {
|
||||
updateNfcInfo();
|
||||
// Zeige Spool-Buttons wenn ein Filament ausgewählt wurde
|
||||
const selectedText = document.getElementById("selected-filament").textContent;
|
||||
@ -490,7 +490,7 @@ function handleSpoolIn(amsId, trayId) {
|
||||
nozzle_temp_max: parseInt(maxTemp),
|
||||
type: selectedSpool.filament.material,
|
||||
brand: selectedSpool.filament.vendor.name,
|
||||
tray_info_idx: selectedSpool.filament.extra.bambu_idx.replace(/['"]+/g, '').trim(),
|
||||
tray_info_idx: selectedSpool.filament.extra.bambu_idx?.replace(/['"]+/g, '').trim() || '',
|
||||
cali_idx: "-1" // Default-Wert setzen
|
||||
}
|
||||
};
|
||||
@ -686,4 +686,4 @@ function showNotification(message, isSuccess) {
|
||||
notification.remove();
|
||||
}, 300);
|
||||
}, 3000);
|
||||
}
|
||||
}
|
160
html/rfid_bambu.html
Normal file
160
html/rfid_bambu.html
Normal file
@ -0,0 +1,160 @@
|
||||
<!-- 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>
|
@ -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>
|
||||
|
@ -55,6 +55,7 @@
|
||||
<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>
|
||||
Enable Auto-TARE <input type="checkbox" id="autoTareCheckbox" onchange="setAutoTare(this.checked);" {{autoTare}}>
|
||||
<div id="statusMessage" class="mt-3"></div>
|
||||
</div>
|
||||
</div>
|
||||
@ -140,6 +141,15 @@
|
||||
}));
|
||||
});
|
||||
|
||||
// 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();
|
||||
</script>
|
||||
|
@ -9,8 +9,8 @@
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[common]
|
||||
version = "1.4.5"
|
||||
to_old_version = "1.4.0"
|
||||
version = "1.5.1"
|
||||
to_old_version = "1.5.0"
|
||||
|
||||
##
|
||||
[env:esp32dev]
|
||||
|
@ -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'))
|
||||
|
22
src/api.cpp
22
src/api.cpp
@ -3,7 +3,8 @@
|
||||
#include <ArduinoJson.h>
|
||||
#include "commonFS.h"
|
||||
|
||||
bool spoolman_connected = false;
|
||||
volatile spoolmanApiStateType spoolmanApiState = API_INIT;
|
||||
//bool spoolman_connected = false;
|
||||
String spoolmanUrl = "";
|
||||
bool octoEnabled = false;
|
||||
String octoUrl = "";
|
||||
@ -85,6 +86,7 @@ JsonDocument fetchSingleSpoolInfo(int spoolId) {
|
||||
}
|
||||
|
||||
void sendToApi(void *parameter) {
|
||||
spoolmanApiState = API_TRANSMITTING;
|
||||
SendToApiParams* params = (SendToApiParams*)parameter;
|
||||
|
||||
// Extrahiere die Werte
|
||||
@ -94,13 +96,16 @@ 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) {
|
||||
@ -165,6 +172,8 @@ bool updateSpoolTagId(String uidString, const char* payload) {
|
||||
NULL // Task-Handle (nicht benötigt)
|
||||
);
|
||||
|
||||
updateDoc.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -201,6 +210,8 @@ uint8_t updateSpoolWeight(String spoolId, uint16_t weight) {
|
||||
NULL // Task-Handle (nicht benötigt)
|
||||
);
|
||||
|
||||
updateDoc.clear();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -238,6 +249,8 @@ bool updateSpoolOcto(int spoolId) {
|
||||
NULL // Task-Handle (nicht benötigt)
|
||||
);
|
||||
|
||||
updateDoc.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -469,7 +482,8 @@ bool checkSpoolmanInstance(const String& url) {
|
||||
return false;
|
||||
}
|
||||
|
||||
spoolman_connected = true;
|
||||
spoolmanApiState = API_IDLE;
|
||||
oledShowTopRow();
|
||||
return strcmp(status, "healthy") == 0;
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,13 @@
|
||||
#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;
|
||||
|
@ -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,32 @@ 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);
|
||||
@ -606,14 +633,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);
|
||||
@ -654,10 +680,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;
|
||||
|
@ -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();
|
||||
|
@ -1,6 +1,20 @@
|
||||
#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) {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <ArduinoJson.h>
|
||||
#include <LittleFS.h>
|
||||
|
||||
bool removeJsonValue(const char* filename);
|
||||
bool saveJsonValue(const char* filename, const JsonDocument& doc);
|
||||
bool loadJsonValue(const char* filename, JsonDocument& doc);
|
||||
void initializeFileSystem();
|
||||
|
@ -19,6 +19,12 @@ 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)
|
||||
|
@ -11,6 +11,8 @@ 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;
|
||||
extern const uint8_t SCREEN_WIDTH;
|
||||
|
@ -177,7 +177,7 @@ void oledShowTopRow() {
|
||||
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_off , 16, 16, WHITE);
|
||||
|
56
src/main.cpp
56
src/main.cpp
@ -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))
|
||||
{
|
||||
@ -100,14 +121,14 @@ void loop() {
|
||||
// Wenn Bambu auto set Spool aktiv
|
||||
if (autoSendToBambu && autoSetToBambuSpoolId > 0)
|
||||
{
|
||||
if (!bambu_connected)
|
||||
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");
|
||||
@ -141,7 +162,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);
|
||||
}
|
||||
@ -154,31 +175,23 @@ 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 < -1)
|
||||
// Abweichung von 2g ignorieren
|
||||
if (autoTare && (weight > 2 && weight < 7) || weight < -2)
|
||||
{
|
||||
if(scaleTareCounter < 5)
|
||||
{
|
||||
scaleTareCounter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
scaleTareRequest = true;
|
||||
scaleTareCounter = 0;
|
||||
}
|
||||
|
||||
scale_tare_counter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
scaleTareCounter = 0;
|
||||
scale_tare_counter = 0;
|
||||
}
|
||||
|
||||
// Prüfen ob das Gewicht gleich bleibt und dann senden
|
||||
if (weight == lastWeight && weight > 5)
|
||||
if (abs(weight - lastWeight) <= 2 && weight > 5)
|
||||
{
|
||||
weigthCouterToApi++;
|
||||
}
|
||||
@ -190,7 +203,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;
|
||||
}
|
||||
@ -198,7 +212,7 @@ 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))
|
||||
{
|
||||
|
28
src/nfc.cpp
28
src/nfc.cpp
@ -18,7 +18,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
|
||||
@ -242,7 +242,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);
|
||||
|
||||
@ -288,7 +288,7 @@ void writeJsonToTag(void *parameter) {
|
||||
//oledShowMessage("NFC-Tag written");
|
||||
oledShowIcon("success");
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
hasReadRfidTag = 5;
|
||||
nfcReaderState = NFC_WRITE_SUCCESS;
|
||||
// aktualisieren der Website wenn sich der Status ändert
|
||||
sendNfcData(nullptr);
|
||||
pauseBambuMqttTask = false;
|
||||
@ -310,7 +310,7 @@ 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
|
||||
@ -318,7 +318,7 @@ void writeJsonToTag(void *parameter) {
|
||||
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);
|
||||
@ -334,7 +334,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
|
||||
@ -351,7 +351,7 @@ void scanRfidTask(void * parameter) {
|
||||
Serial.println("RFID Task gestartet");
|
||||
for(;;) {
|
||||
// Wenn geschrieben wird Schleife aussetzen
|
||||
if (hasReadRfidTag != 3)
|
||||
if (nfcReaderState != NFC_WRITING)
|
||||
{
|
||||
yield();
|
||||
|
||||
@ -363,12 +363,12 @@ void scanRfidTask(void * parameter) {
|
||||
|
||||
foundNfcTag(nullptr, success);
|
||||
|
||||
if (success && hasReadRfidTag != 1)
|
||||
if (success && nfcReaderState != NFC_READ_SUCCESS)
|
||||
{
|
||||
// Display some basic information about the card
|
||||
Serial.println("Found an ISO14443A card");
|
||||
|
||||
hasReadRfidTag = 6;
|
||||
nfcReaderState = NFC_READING;
|
||||
|
||||
oledShowIcon("transfer");
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
@ -406,11 +406,11 @@ void scanRfidTask(void * parameter) {
|
||||
{
|
||||
oledShowMessage("NFC-Tag unknown");
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
hasReadRfidTag = 2;
|
||||
nfcReaderState = NFC_READ_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
hasReadRfidTag = 1;
|
||||
nfcReaderState = NFC_READ_SUCCESS;
|
||||
}
|
||||
|
||||
free(data);
|
||||
@ -418,7 +418,7 @@ void scanRfidTask(void * parameter) {
|
||||
else
|
||||
{
|
||||
oledShowMessage("NFC-Tag read error");
|
||||
hasReadRfidTag = 2;
|
||||
nfcReaderState = NFC_READ_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -427,9 +427,9 @@ void scanRfidTask(void * parameter) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!success && hasReadRfidTag > 0)
|
||||
if (!success && nfcReaderState != NFC_IDLE)
|
||||
{
|
||||
hasReadRfidTag = 0;
|
||||
nfcReaderState = NFC_IDLE;
|
||||
//uidString = "";
|
||||
nfcJsonData = "";
|
||||
Serial.println("Tag entfernt");
|
||||
|
14
src/nfc.h
14
src/nfc.h
@ -3,6 +3,16 @@
|
||||
|
||||
#include <Arduino.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 scanRfidTask(void * parameter);
|
||||
void startWriteJsonToTag(const char* payload);
|
||||
@ -10,7 +20,9 @@ void startWriteJsonToTag(const char* payload);
|
||||
extern TaskHandle_t RfidReaderTask;
|
||||
extern String nfcJsonData;
|
||||
extern String spoolId;
|
||||
extern volatile uint8_t hasReadRfidTag;
|
||||
extern volatile nfcReaderStateType nfcReaderState;
|
||||
extern volatile bool pauseBambuMqttTask;
|
||||
|
||||
|
||||
|
||||
#endif
|
33
src/ota.cpp
33
src/ota.cpp
@ -1,6 +1,10 @@
|
||||
#include <Arduino.h>
|
||||
#include <website.h>
|
||||
#include <commonFS.h>
|
||||
#include "scale.h"
|
||||
#include "bambu.h"
|
||||
#include "nfc.h"
|
||||
|
||||
|
||||
// Globale Variablen für Config Backups hinzufügen
|
||||
String bambuCredentialsBackup;
|
||||
@ -151,6 +155,25 @@ void handleUpdate(AsyncWebServer &server) {
|
||||
|
||||
updateHandler->onUpload([](AsyncWebServerRequest *request, String filename,
|
||||
size_t index, uint8_t *data, size_t len, bool final) {
|
||||
|
||||
// Disable all Tasks
|
||||
if (BambuMqttTask != NULL)
|
||||
{
|
||||
Serial.println("Delete BambuMqttTask");
|
||||
vTaskDelete(BambuMqttTask);
|
||||
BambuMqttTask = NULL;
|
||||
}
|
||||
if (ScaleTask) {
|
||||
Serial.println("Delete ScaleTask");
|
||||
vTaskDelete(ScaleTask);
|
||||
ScaleTask = NULL;
|
||||
}
|
||||
if (RfidReaderTask) {
|
||||
Serial.println("Delete RfidReaderTask");
|
||||
vTaskDelete(RfidReaderTask);
|
||||
RfidReaderTask = NULL;
|
||||
}
|
||||
|
||||
if (!index) {
|
||||
updateTotalSize = request->contentLength();
|
||||
updateWritten = 0;
|
||||
@ -159,9 +182,9 @@ void handleUpdate(AsyncWebServer &server) {
|
||||
if (isSpiffsUpdate) {
|
||||
// Backup vor dem Update
|
||||
sendUpdateProgress(0, "backup", "Backing up configurations...");
|
||||
delay(200);
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||
backupJsonConfigs();
|
||||
delay(200);
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||
|
||||
const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, NULL);
|
||||
if (!partition || !Update.begin(partition->size, U_SPIFFS)) {
|
||||
@ -169,14 +192,14 @@ void handleUpdate(AsyncWebServer &server) {
|
||||
return;
|
||||
}
|
||||
sendUpdateProgress(5, "starting", "Starting SPIFFS update...");
|
||||
delay(200);
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||
} else {
|
||||
if (!Update.begin(updateTotalSize)) {
|
||||
request->send(400, "application/json", "{\"success\":false,\"message\":\"Update initialization failed\"}");
|
||||
return;
|
||||
}
|
||||
sendUpdateProgress(0, "starting", "Starting firmware update...");
|
||||
delay(200);
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,7 +225,7 @@ void handleUpdate(AsyncWebServer &server) {
|
||||
if (currentProgress != lastProgress && (currentProgress % 10 == 0 || final)) {
|
||||
sendUpdateProgress(currentProgress, "uploading");
|
||||
oledShowMessage("Update: " + String(currentProgress) + "%");
|
||||
delay(50);
|
||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||
lastProgress = currentProgress;
|
||||
}
|
||||
}
|
||||
|
@ -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,8 +22,23 @@ uint8_t scaleCalibrated = 1;
|
||||
Preferences preferences;
|
||||
const char* NVS_NAMESPACE = "scale";
|
||||
const char* NVS_KEY_CALIBRATION = "cal_value";
|
||||
const char* NVS_KEY_AUTOTARE = "auto_tare";
|
||||
bool autoTare = true;
|
||||
|
||||
// ##### Funktionen für Waage #####
|
||||
uint8_t setAutoTare(bool autoTareValue) {
|
||||
Serial.print("Set AutoTare to ");
|
||||
Serial.println(autoTareValue);
|
||||
autoTare = autoTareValue;
|
||||
|
||||
// Speichern mit NVS
|
||||
preferences.begin(NVS_NAMESPACE, false); // false = readwrite
|
||||
preferences.putBool(NVS_KEY_AUTOTARE, autoTare);
|
||||
preferences.end();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t tareScale() {
|
||||
Serial.println("Tare scale");
|
||||
scale.tare();
|
||||
@ -38,11 +54,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 +81,20 @@ 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,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;
|
||||
|
||||
|
@ -22,14 +22,14 @@ 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);
|
||||
@ -44,13 +44,15 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
|
||||
JsonDocument doc;
|
||||
deserializeJson(doc, message);
|
||||
|
||||
bool spoolmanConnected = (spoolmanApiState != API_INIT);
|
||||
|
||||
if (doc["type"] == "heartbeat") {
|
||||
// Sende Heartbeat-Antwort
|
||||
ws.text(client->id(), "{"
|
||||
"\"type\":\"heartbeat\","
|
||||
"\"freeHeap\":" + String(ESP.getFreeHeap()/1024) + ","
|
||||
"\"bambu_connected\":" + String(bambu_connected) + ","
|
||||
"\"spoolman_connected\":" + String(spoolman_connected) + ""
|
||||
"\"spoolman_connected\":" + String(spoolmanConnected) + ""
|
||||
"}");
|
||||
}
|
||||
|
||||
@ -73,6 +75,10 @@ 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 +145,31 @@ void foundNfcTag(AsyncWebSocketClient *client, uint8_t success) {
|
||||
}
|
||||
|
||||
void sendNfcData(AsyncWebSocketClient *client) {
|
||||
if (lastHasReadRfidTag == hasReadRfidTag) return;
|
||||
if (hasReadRfidTag == 0) {
|
||||
ws.textAll("{\"type\":\"nfcData\", \"payload\":{}}");
|
||||
if (lastnfcReaderState == nfcReaderState) return;
|
||||
// TBD: Why is there no status for reading the tag?
|
||||
switch(nfcReaderState){
|
||||
case NFC_IDLE:
|
||||
ws.textAll("{\"type\":\"nfcData\", \"payload\":{}}");
|
||||
break;
|
||||
case NFC_READ_SUCCESS:
|
||||
ws.textAll("{\"type\":\"nfcData\", \"payload\":" + nfcJsonData + "}");
|
||||
break;
|
||||
case NFC_READ_ERROR:
|
||||
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Empty Tag or Data not readable\"}}");
|
||||
break;
|
||||
case NFC_WRITING:
|
||||
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Schreibe Tag...\"}}");
|
||||
break;
|
||||
case NFC_WRITE_SUCCESS:
|
||||
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Tag erfolgreich geschrieben\"}}");
|
||||
break;
|
||||
case NFC_WRITE_ERROR:
|
||||
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Error writing to Tag\"}}");
|
||||
break;
|
||||
case DEFAULT:
|
||||
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Something went wrong\"}}");
|
||||
}
|
||||
else if (hasReadRfidTag == 1) {
|
||||
ws.textAll("{\"type\":\"nfcData\", \"payload\":" + nfcJsonData + "}");
|
||||
}
|
||||
else if (hasReadRfidTag == 2)
|
||||
{
|
||||
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Empty Tag or Data not readable\"}}");
|
||||
}
|
||||
else if (hasReadRfidTag == 3)
|
||||
{
|
||||
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)
|
||||
{
|
||||
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Tag erfolgreich geschrieben\"}}");
|
||||
}
|
||||
else
|
||||
{
|
||||
ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Something went wrong\"}}");
|
||||
}
|
||||
lastHasReadRfidTag = hasReadRfidTag;
|
||||
lastnfcReaderState = nfcReaderState;
|
||||
}
|
||||
|
||||
void sendAmsData(AsyncWebSocketClient *client) {
|
||||
@ -204,16 +207,23 @@ void setupWebserver(AsyncWebServer &server) {
|
||||
// Route für Waage
|
||||
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);
|
||||
@ -310,6 +320,15 @@ void setupWebserver(AsyncWebServer &server) {
|
||||
|
||||
// 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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user