Merge branch 'temp-branch'
This commit is contained in:
		
							
								
								
									
										86
									
								
								.github/workflows/providers/gitea-release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										86
									
								
								.github/workflows/providers/gitea-release.yml
									
									
									
									
										vendored
									
									
								
							| @@ -37,42 +37,51 @@ jobs: | ||||
|         sudo apt-get update | ||||
|         sudo apt-get install xxd | ||||
|      | ||||
|     - name: Check for SPIFFS changes | ||||
|       id: check_spiffs | ||||
|       run: | | ||||
|         git fetch --unshallow || true | ||||
|         CHANGED_FILES=$(git diff --name-only HEAD^..HEAD) | ||||
|         if echo "$CHANGED_FILES" | grep -q "^data/\|^html/"; then | ||||
|           echo "SPIFFS_CHANGED=true" >> $GITHUB_OUTPUT | ||||
|         else | ||||
|           echo "SPIFFS_CHANGED=false" >> $GITHUB_OUTPUT | ||||
|         fi | ||||
|      | ||||
|     - name: Build Firmware | ||||
|       run: | | ||||
|         pio run -e esp32dev -t buildfs  # Build SPIFFS | ||||
|         pio run -e esp32dev            # Build firmware | ||||
|         cp .pio/build/esp32dev/firmware.bin .pio/build/esp32dev/filaman.bin | ||||
|         cp .pio/build/esp32dev/spiffs.bin .pio/build/esp32dev/filaman_spiffs.bin | ||||
|         # Get version from platformio.ini | ||||
|         VERSION=$(grep '^version = ' platformio.ini | cut -d'"' -f2) | ||||
|          | ||||
|         # Always build firmware | ||||
|         pio run -e esp32dev | ||||
|         cp .pio/build/esp32dev/firmware.bin .pio/build/esp32dev/filaman_${VERSION}.bin | ||||
|          | ||||
|         # Only build SPIFFS if changed | ||||
|         if [[ "${{ steps.check_spiffs.outputs.SPIFFS_CHANGED }}" == "true" ]]; then | ||||
|           echo "Building SPIFFS due to changes..." | ||||
|           cp .pio/build/esp32dev/spiffs.bin .pio/build/esp32dev/webpage_${VERSION}.bin | ||||
|         fi | ||||
|          | ||||
|     - name: Prepare binaries | ||||
|       run: | | ||||
|         # Ensure we're in the project root | ||||
|         cd $GITHUB_WORKSPACE | ||||
|          | ||||
|         # Create SPIFFS directory if it doesn't exist | ||||
|         mkdir -p .pio/build/esp32dev/spiffs | ||||
|          | ||||
|         # Copy firmware to SPIFFS directory | ||||
|         cp .pio/build/esp32dev/firmware.bin .pio/build/esp32dev/spiffs/firmware.bin | ||||
|          | ||||
|         # Build new SPIFFS image with firmware included | ||||
|         pio run -t buildfs | ||||
|          | ||||
|         cd .pio/build/esp32dev | ||||
|         VERSION=$(grep '^version = ' ../../platformio.ini | cut -d'"' -f2) | ||||
|          | ||||
|         # Create release files | ||||
|         cp spiffs.bin filaman_spiffs.bin | ||||
|          | ||||
|         # Create full binary with correct partition offsets | ||||
|         echo "Creating full binary..." | ||||
|         esptool.py --chip esp32 merge_bin \ | ||||
|           --flash_mode dio \ | ||||
|           --flash_freq 40m \ | ||||
|           -o filaman_full.bin \ | ||||
|           0x1000 bootloader.bin \ | ||||
|           0x8000 partitions.bin \ | ||||
|           0x10000 firmware.bin \ | ||||
|           0x310000 spiffs.bin | ||||
|         # Create full binary only if SPIFFS changed | ||||
|         if [[ "${{ steps.check_spiffs.outputs.SPIFFS_CHANGED }}" == "true" ]]; then | ||||
|           echo "Creating full binary..." | ||||
|           esptool.py --chip esp32 merge_bin \ | ||||
|             --fill-flash-size 4MB \ | ||||
|             --flash_mode dio \ | ||||
|             --flash_freq 40m \ | ||||
|             --flash_size 4MB \ | ||||
|             -o filaman_full_${VERSION}.bin \ | ||||
|             0x0000 bootloader.bin \ | ||||
|             0x8000 partitions.bin \ | ||||
|             0x10000 firmware.bin \ | ||||
|             0x390000 spiffs.bin | ||||
|         fi | ||||
|          | ||||
|         # Verify file sizes | ||||
|         echo "File sizes:" | ||||
| @@ -85,6 +94,7 @@ jobs: | ||||
|         TAG="${{ inputs.gitea_ref_name }}" | ||||
|         API_URL="${{ inputs.gitea_server_url }}/api/v1" | ||||
|         REPO="${{ inputs.gitea_repository }}" | ||||
|         VERSION=$(grep '^version = ' platformio.ini | cut -d'"' -f2) | ||||
|          | ||||
|         # Create release | ||||
|         RESPONSE=$(curl -k -s \ | ||||
| @@ -102,12 +112,20 @@ jobs: | ||||
|          | ||||
|         if [ -n "$RELEASE_ID" ]; then | ||||
|           echo "Release created with ID: $RELEASE_ID" | ||||
|            | ||||
|           # Upload binaries | ||||
|           cd .pio/build/esp32dev | ||||
|            | ||||
|           # Check if files exist before uploading | ||||
|           for file in filaman_spiffs.bin filaman_full.bin; do | ||||
|           # Always upload firmware | ||||
|           if [ -f "filaman_${VERSION}.bin" ]; then | ||||
|             curl -k -s \ | ||||
|               -X POST \ | ||||
|               -H "Authorization: token ${TOKEN}" \ | ||||
|               -H "Content-Type: application/octet-stream" \ | ||||
|               --data-binary "@filaman_${VERSION}.bin" \ | ||||
|               "${API_URL}/repos/${REPO}/releases/${RELEASE_ID}/assets?name=filaman_${VERSION}.bin" | ||||
|           fi | ||||
|            | ||||
|           # Upload SPIFFS and full binary only if they exist | ||||
|           for file in webpage_${VERSION}.bin filaman_full_${VERSION}.bin; do | ||||
|             if [ -f "$file" ]; then | ||||
|               echo "Uploading $file..." | ||||
|               curl -k -s \ | ||||
| @@ -116,8 +134,6 @@ jobs: | ||||
|                 -H "Content-Type: application/octet-stream" \ | ||||
|                 --data-binary "@$file" \ | ||||
|                 "${API_URL}/repos/${REPO}/releases/${RELEASE_ID}/assets?name=$file" | ||||
|             else | ||||
|               echo "Warning: $file not found" | ||||
|             fi | ||||
|           done | ||||
|         else | ||||
|   | ||||
							
								
								
									
										93
									
								
								.github/workflows/providers/github-release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										93
									
								
								.github/workflows/providers/github-release.yml
									
									
									
									
										vendored
									
									
								
							| @@ -26,42 +26,51 @@ jobs: | ||||
|         sudo apt-get update | ||||
|         sudo apt-get install xxd | ||||
|      | ||||
|     - name: Check for SPIFFS changes | ||||
|       id: check_spiffs | ||||
|       run: | | ||||
|         git fetch --unshallow || true | ||||
|         CHANGED_FILES=$(git diff --name-only HEAD^..HEAD) | ||||
|         if echo "$CHANGED_FILES" | grep -q "^data/\|^html/"; then | ||||
|           echo "SPIFFS_CHANGED=true" >> $GITHUB_OUTPUT | ||||
|         else | ||||
|           echo "SPIFFS_CHANGED=false" >> $GITHUB_OUTPUT | ||||
|         fi | ||||
|      | ||||
|     - name: Build Firmware | ||||
|       run: | | ||||
|         pio run -e esp32dev -t buildfs  # Build SPIFFS | ||||
|         pio run -e esp32dev            # Build firmware | ||||
|         cp .pio/build/esp32dev/firmware.bin .pio/build/esp32dev/filaman.bin | ||||
|         cp .pio/build/esp32dev/spiffs.bin .pio/build/esp32dev/filaman_spiffs.bin | ||||
|         # Get version from platformio.ini | ||||
|         VERSION=$(grep '^version = ' platformio.ini | cut -d'"' -f2) | ||||
|          | ||||
|         # Always build firmware | ||||
|         pio run -e esp32dev | ||||
|         cp .pio/build/esp32dev/firmware.bin .pio/build/esp32dev/filaman_${VERSION}.bin | ||||
|          | ||||
|         # Only build SPIFFS if changed | ||||
|         if [[ "${{ steps.check_spiffs.outputs.SPIFFS_CHANGED }}" == "true" ]]; then | ||||
|           echo "Building SPIFFS due to changes..." | ||||
|           cp .pio/build/esp32dev/spiffs.bin .pio/build/esp32dev/webpage_${VERSION}.bin | ||||
|         fi | ||||
|          | ||||
|     - name: Prepare binaries | ||||
|       run: | | ||||
|         # Ensure we're in the project root | ||||
|         cd $GITHUB_WORKSPACE | ||||
|          | ||||
|         # Create SPIFFS directory if it doesn't exist | ||||
|         mkdir -p .pio/build/esp32dev/spiffs | ||||
|          | ||||
|         # Copy firmware to SPIFFS directory | ||||
|         cp .pio/build/esp32dev/firmware.bin .pio/build/esp32dev/spiffs/firmware.bin | ||||
|          | ||||
|         # Build new SPIFFS image with firmware included | ||||
|         pio run -t buildfs | ||||
|          | ||||
|         cd .pio/build/esp32dev | ||||
|         VERSION=$(grep '^version = ' ../../platformio.ini | cut -d'"' -f2) | ||||
|          | ||||
|         # Create release files | ||||
|         cp spiffs.bin filaman_spiffs.bin | ||||
|          | ||||
|         # Create full binary without filling unused space | ||||
|         echo "Creating full binary..." | ||||
|         esptool.py --chip esp32 merge_bin \ | ||||
|           --flash_mode dio \ | ||||
|           --flash_freq 40m \ | ||||
|           -o filaman_full.bin \ | ||||
|           0x1000 bootloader.bin \ | ||||
|           0x8000 partitions.bin \ | ||||
|           0x10000 firmware.bin \ | ||||
|           0x310000 spiffs.bin | ||||
|         # Create full binary only if SPIFFS changed | ||||
|         if [[ "${{ steps.check_spiffs.outputs.SPIFFS_CHANGED }}" == "true" ]]; then | ||||
|           echo "Creating full binary..." | ||||
|           esptool.py --chip esp32 merge_bin \ | ||||
|             --fill-flash-size 4MB \ | ||||
|             --flash_mode dio \ | ||||
|             --flash_freq 40m \ | ||||
|             --flash_size 4MB \ | ||||
|             -o filaman_full_${VERSION}.bin \ | ||||
|             0x0000 bootloader.bin \ | ||||
|             0x8000 partitions.bin \ | ||||
|             0x10000 firmware.bin \ | ||||
|             0x390000 spiffs.bin | ||||
|         fi | ||||
|          | ||||
|         # Verify file sizes | ||||
|         echo "File sizes:" | ||||
| @@ -85,16 +94,23 @@ jobs: | ||||
|       env: | ||||
|         GH_TOKEN: ${{ github.token }} | ||||
|       run: | | ||||
|         # Check which files exist and create a list for upload | ||||
|         cd .pio/build/esp32dev | ||||
|         VERSION=$(grep '^version = ' ../../platformio.ini | cut -d'"' -f2) | ||||
|         FILES_TO_UPLOAD="" | ||||
|         for file in filaman_spiffs.bin filaman_full.bin; do | ||||
|           if [ -f "$file" ]; then | ||||
|             FILES_TO_UPLOAD="$FILES_TO_UPLOAD .pio/build/esp32dev/$file" | ||||
|           else | ||||
|             echo "Warning: $file not found" | ||||
|           fi | ||||
|         done | ||||
|          | ||||
|         # Always add firmware | ||||
|         if [ -f "filaman_${VERSION}.bin" ]; then | ||||
|           FILES_TO_UPLOAD="$FILES_TO_UPLOAD filaman_${VERSION}.bin" | ||||
|         fi | ||||
|          | ||||
|         # Add SPIFFS and full binary only if they exist | ||||
|         if [ -f "webpage_${VERSION}.bin" ]; then | ||||
|           FILES_TO_UPLOAD="$FILES_TO_UPLOAD webpage_${VERSION}.bin" | ||||
|         fi | ||||
|          | ||||
|         if [ -f "filaman_full_${VERSION}.bin" ]; then | ||||
|           FILES_TO_UPLOAD="$FILES_TO_UPLOAD filaman_full_${VERSION}.bin" | ||||
|         fi | ||||
|          | ||||
|         # Create release with available files | ||||
|         if [ -n "$FILES_TO_UPLOAD" ]; then | ||||
| @@ -104,4 +120,5 @@ jobs: | ||||
|             $FILES_TO_UPLOAD | ||||
|         else | ||||
|           echo "Error: No files found to upload" | ||||
|           exit 1 | ||||
|           exit 1 | ||||
|         fi | ||||
							
								
								
									
										20
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -1,23 +1,13 @@ | ||||
| # Changelog | ||||
|  | ||||
| ## [1.2.94] - 2025-02-21 | ||||
| ### Changed | ||||
| - update webpages for version v1.2.94 | ||||
| - remove unused flash size parameters in release workflows | ||||
|  | ||||
|  | ||||
| ## [1.2.93] - 2025-02-21 | ||||
| ### Changed | ||||
| - update webpages for version v1.2.93 | ||||
| - update SPIFFS initialization and partition sizes; enhance WiFi setup | ||||
|  | ||||
|  | ||||
| ## [1.2.92] - 2025-02-21 | ||||
| ## [1.2.95] - 2025-02-21 | ||||
| ### Added | ||||
| - enhance OTA upload handling with chunk validation and timeout checks | ||||
| - enhance update process with separate forms for firmware and webpage uploads, including validation and improved UI | ||||
| - add API endpoint for version retrieval and update HTML to display dynamic version | ||||
|  | ||||
| ### Changed | ||||
| - update webpages for version v1.2.92 | ||||
| - update webpages for version v1.2.95 | ||||
| - bump version to 1.2.94 in platformio.ini | ||||
|  | ||||
|  | ||||
| ## [1.2.91] - 2025-02-20 | ||||
|   | ||||
| @@ -6,13 +6,24 @@ | ||||
|     <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">v1.2.94</span></h1> | ||||
|                 <h1>FilaMan<span class="version"></span></h1> | ||||
|                 <h4>Filament Management Tool</h4> | ||||
|             </div> | ||||
|         </div> | ||||
| @@ -33,4 +44,6 @@ | ||||
|             <div class="ram-status" id="ramStatus"></div> | ||||
|         </div> | ||||
|     </div> | ||||
| </body> | ||||
| </html> | ||||
|  | ||||
|   | ||||
| @@ -6,13 +6,24 @@ | ||||
|     <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">v1.2.94</span></h1> | ||||
|                 <h1>FilaMan<span class="version"></span></h1> | ||||
|                 <h4>Filament Management Tool</h4> | ||||
|             </div> | ||||
|         </div> | ||||
| @@ -33,6 +44,8 @@ | ||||
|             <div class="ram-status" id="ramStatus"></div> | ||||
|         </div> | ||||
|     </div> | ||||
| </body> | ||||
| </html> | ||||
|  | ||||
| <!-- head --> | ||||
|  | ||||
|   | ||||
| @@ -6,13 +6,24 @@ | ||||
|     <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">v1.2.94</span></h1> | ||||
|                 <h1>FilaMan<span class="version"></span></h1> | ||||
|                 <h4>Filament Management Tool</h4> | ||||
|             </div> | ||||
|         </div> | ||||
| @@ -33,6 +44,8 @@ | ||||
|             <div class="ram-status" id="ramStatus"></div> | ||||
|         </div> | ||||
|     </div> | ||||
| </body> | ||||
| </html> | ||||
|  | ||||
| <!-- head --> | ||||
|  | ||||
|   | ||||
| @@ -6,13 +6,24 @@ | ||||
|     <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">v1.2.94</span></h1> | ||||
|                 <h1>FilaMan<span class="version"></span></h1> | ||||
|                 <h4>Filament Management Tool</h4> | ||||
|             </div> | ||||
|         </div> | ||||
| @@ -33,6 +44,8 @@ | ||||
|             <div class="ram-status" id="ramStatus"></div> | ||||
|         </div> | ||||
|     </div> | ||||
| </body> | ||||
| </html> | ||||
|  | ||||
| <!-- head --> | ||||
|  | ||||
|   | ||||
| @@ -5,59 +5,131 @@ | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|     <title>FilaMan - Firmware Update</title> | ||||
|     <link rel="stylesheet" href="style.css"> | ||||
|     <style> | ||||
|         .debug-log { | ||||
|             background: #f5f5f5; | ||||
|             border: 1px solid #ddd; | ||||
|             padding: 10px; | ||||
|             margin: 10px 0; | ||||
|             font-family: monospace; | ||||
|             max-height: 200px; | ||||
|             overflow-y: auto; | ||||
|             display: none; | ||||
|         } | ||||
|     </style> | ||||
|     <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> | ||||
| </body> | ||||
| </html> | ||||
|  | ||||
| <!-- head --> | ||||
|      | ||||
|     <div class="content"> | ||||
|         <h1>Firmware Update</h1> | ||||
|          | ||||
|         <h1>System Update</h1> | ||||
|         <div class="warning"> | ||||
|             <strong>Warning:</strong> Do not power off the device during update. | ||||
|         </div> | ||||
|  | ||||
|         <form id="updateForm"> | ||||
|             <input type="file" name="update" accept=".bin"> | ||||
|             <button type="submit">Update Firmware</button> | ||||
|         </form> | ||||
|         <div class="update-options"> | ||||
|             <div class="update-section"> | ||||
|                 <h2>Firmware Update</h2> | ||||
|                 <p>Upload a new firmware file (filaman_*.bin)</p> | ||||
|                 <div class="update-form"> | ||||
|                     <form id="firmwareForm" enctype='multipart/form-data' data-type="firmware"> | ||||
|                         <input type='file' name='update' accept='.bin' required> | ||||
|                         <input type='submit' value='Start Firmware Update'> | ||||
|                     </form> | ||||
|                 </div> | ||||
|             </div> | ||||
|  | ||||
|         <div class="progress" style="display: none;"> | ||||
|             <div class="progress-bar"></div> | ||||
|             <div class="status"></div> | ||||
|             <div class="update-section"> | ||||
|                 <h2>Webpage Update</h2> | ||||
|                 <p>Upload a new webpage file (webpage_*.bin)</p> | ||||
|                 <div class="update-form"> | ||||
|                     <form id="webpageForm" enctype='multipart/form-data' data-type="webpage"> | ||||
|                         <input type='file' name='update' accept='.bin' required> | ||||
|                         <input type='submit' value='Start Webpage Update'> | ||||
|                     </form> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <div class="debug-log"></div> | ||||
|         <div class="progress-container" style="display: none;"> | ||||
|             <div class="progress-bar">0%</</div> | ||||
|         </div> | ||||
|         <div class="status"></div> | ||||
|     </div> | ||||
|  | ||||
|     <script> | ||||
|         const form = document.getElementById('updateForm'); | ||||
|         const progress = document.querySelector('.progress'); | ||||
|         const progressBar = document.querySelector('.progress-bar'); | ||||
|         const status = document.querySelector('.status'); | ||||
|         const debugLog = document.querySelector('.debug-log'); | ||||
|     <style> | ||||
|         .update-options { | ||||
|             display: flex; | ||||
|             gap: 2rem; | ||||
|             margin: 2rem 0; | ||||
|         } | ||||
|         .update-section { | ||||
|             flex: 1; | ||||
|             background: #f5f5f5; | ||||
|             padding: 1.5rem; | ||||
|             border-radius: 8px; | ||||
|         } | ||||
|         .update-section h2 { | ||||
|             margin-top: 0; | ||||
|             color: #333; | ||||
|         } | ||||
|         .update-section p { | ||||
|             color: #666; | ||||
|             margin-bottom: 1rem; | ||||
|         } | ||||
|     </style> | ||||
|  | ||||
|         function log(message) { | ||||
|             debugLog.style.display = 'block'; | ||||
|             const time = new Date().toLocaleTimeString(); | ||||
|             debugLog.innerHTML += `[${time}] ${message}<br>`; | ||||
|             debugLog.scrollTop = debugLog.scrollHeight; | ||||
|     <script> | ||||
|         // Hide status indicators during update | ||||
|         const statusContainer = document.querySelector('.status-container'); | ||||
|         if (statusContainer) { | ||||
|             statusContainer.style.display = 'none'; | ||||
|         } | ||||
|  | ||||
|         form.addEventListener('submit', async (e) => { | ||||
|         function handleUpdate(e) { | ||||
|             e.preventDefault(); | ||||
|             const file = form.update.files[0]; | ||||
|             const updateType = form.dataset.type; | ||||
|  | ||||
|             if (!file) { | ||||
|                 alert('Please select a file'); | ||||
|                 alert('Please select a file.'); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             // Validate file name pattern | ||||
|             if (updateType === 'firmware' && !file.name.startsWith('filaman_')) { | ||||
|                 alert('Please select a valid firmware file (filaman_*.bin)'); | ||||
|                 return; | ||||
|             } | ||||
|             if (updateType === 'webpage' && !file.name.startsWith('webpage_')) { | ||||
|                 alert('Please select a valid webpage file (webpage_*.bin)'); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
| @@ -70,49 +142,84 @@ | ||||
|             // Erstelle FormData für den Upload | ||||
|             const formData = new FormData(); | ||||
|             formData.append('update', file); | ||||
|              | ||||
|             const progress = document.querySelector('.progress-bar'); | ||||
|             const progressContainer = document.querySelector('.progress-container'); | ||||
|             const status = document.querySelector('.status'); | ||||
|              | ||||
|             progressContainer.style.display = 'block'; | ||||
|             status.style.display = 'none'; | ||||
|             status.className = 'status'; | ||||
|  | ||||
|             try { | ||||
|                 log('Starting upload...'); | ||||
|                 const response = await fetch('/update', { | ||||
|                     method: 'POST', | ||||
|                     body: formData | ||||
|                 }); | ||||
|             // Disable both forms during update | ||||
|             document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = true); | ||||
|  | ||||
|                 log(`Server responded with status: ${response.status}`); | ||||
|  | ||||
|                 let result; | ||||
|                 const contentType = response.headers.get('content-type'); | ||||
|                 log(`Response content-type: ${contentType}`); | ||||
|  | ||||
|                 if (contentType && contentType.includes('application/json')) { | ||||
|                     result = await response.json(); | ||||
|                     log('Received JSON response'); | ||||
|                 } else { | ||||
|                     const text = await response.text(); | ||||
|                     log(`Received text response: ${text}`); | ||||
|                     result = { success: response.ok, message: text }; | ||||
|             const xhr = new XMLHttpRequest(); | ||||
|             xhr.open('POST', '/update', true); | ||||
|             xhr.upload.onprogress = (e) => { | ||||
|                 if (e.lengthComputable) { | ||||
|                     const percentComplete = (e.loaded / e.total) * 100; | ||||
|                     progress.style.width = percentComplete + '%'; | ||||
|                     progress.textContent = Math.round(percentComplete) + '%'; | ||||
|                 } | ||||
|                  | ||||
|                 log(`Update result: ${JSON.stringify(result)}`); | ||||
|                  | ||||
|                 if (response.ok && result.success) { | ||||
|                     status.textContent = 'Update successful! Restarting...'; | ||||
|                     status.className = 'success'; | ||||
|                     setTimeout(() => { | ||||
|                         window.location.href = '/'; | ||||
|                     }, 5000); | ||||
|                 } else { | ||||
|                     throw new Error(result.message || 'Update failed'); | ||||
|             }; | ||||
|  | ||||
|             xhr.onload = function() { | ||||
|                 try { | ||||
|                     let response = this.responseText; | ||||
|                     try { | ||||
|                         const jsonResponse = JSON.parse(response); | ||||
|                         response = jsonResponse.message; | ||||
|                          | ||||
|                         if (jsonResponse.restart) { | ||||
|                             status.textContent = response + " Redirecting in 20 seconds..."; | ||||
|                             let countdown = 20; | ||||
|                             const timer = setInterval(() => { | ||||
|                                 countdown--; | ||||
|                                 if (countdown <= 0) { | ||||
|                                     clearInterval(timer); | ||||
|                                     window.location.href = '/'; | ||||
|                                 } else { | ||||
|                                     status.textContent = response + ` Redirecting in ${countdown} seconds...`; | ||||
|                                 } | ||||
|                             }, 1000); | ||||
|                         } | ||||
|                     } catch (e) { | ||||
|                         if (!isNaN(response)) { | ||||
|                             const percent = parseInt(response); | ||||
|                             progress.style.width = percent + '%'; | ||||
|                             progress.textContent = percent + '%'; | ||||
|                             return; | ||||
|                         } | ||||
|                     } | ||||
|                      | ||||
|                     status.textContent = response; | ||||
|                     status.classList.add(xhr.status === 200 ? 'success' : 'error'); | ||||
|                     status.style.display = 'block'; | ||||
|                      | ||||
|                     if (xhr.status !== 200) { | ||||
|                         document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = false); | ||||
|                     } | ||||
|                 } catch (error) { | ||||
|                     status.textContent = 'Error: ' + error.message; | ||||
|                     status.classList.add('error'); | ||||
|                     status.style.display = 'block'; | ||||
|                     document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = false); | ||||
|                 } | ||||
|             } catch (error) { | ||||
|                 log(`Error: ${error.message}`); | ||||
|                 console.error('Update error:', error); | ||||
|                 status.textContent = `Error: ${error.message}`; | ||||
|                 status.className = 'error'; | ||||
|                 form.style.display = 'block'; | ||||
|                 progress.style.display = 'none'; | ||||
|             } | ||||
|         }); | ||||
|             }; | ||||
|  | ||||
|             xhr.onerror = function() { | ||||
|                 status.textContent = 'Update failed: Network error'; | ||||
|                 status.classList.add('error'); | ||||
|                 status.style.display = 'block'; | ||||
|                 document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = false); | ||||
|             }; | ||||
|  | ||||
|             xhr.send(formData); | ||||
|         } | ||||
|  | ||||
|         document.getElementById('firmwareForm').addEventListener('submit', handleUpdate); | ||||
|         document.getElementById('webpageForm').addEventListener('submit', handleUpdate); | ||||
|     </script> | ||||
| </body> | ||||
| </html> | ||||
| @@ -6,13 +6,24 @@ | ||||
|     <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">v1.2.94</span></h1> | ||||
|                 <h1>FilaMan<span class="version"></span></h1> | ||||
|                 <h4>Filament Management Tool</h4> | ||||
|             </div> | ||||
|         </div> | ||||
| @@ -33,6 +44,8 @@ | ||||
|             <div class="ram-status" id="ramStatus"></div> | ||||
|         </div> | ||||
|     </div> | ||||
| </body> | ||||
| </html> | ||||
|  | ||||
| <!-- head --> | ||||
|  | ||||
|   | ||||
| @@ -6,13 +6,24 @@ | ||||
|     <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">v1.2.94</span></h1> | ||||
|                 <h1>FilaMan<span class="version"></span></h1> | ||||
|                 <h4>Filament Management Tool</h4> | ||||
|             </div> | ||||
|         </div> | ||||
| @@ -33,6 +44,8 @@ | ||||
|             <div class="ram-status" id="ramStatus"></div> | ||||
|         </div> | ||||
|     </div> | ||||
| </body> | ||||
| </html> | ||||
|  | ||||
| <!-- head --> | ||||
|  | ||||
|   | ||||
| @@ -9,7 +9,7 @@ | ||||
| ; https://docs.platformio.org/page/projectconf.html | ||||
|  | ||||
| [common] | ||||
| version = "1.2.94" | ||||
| version = "1.2.95" | ||||
|  | ||||
| [env:esp32dev] | ||||
| platform = espressif32 | ||||
| @@ -50,26 +50,20 @@ build_flags = | ||||
|     -DCORE_DEBUG_LEVEL=3 | ||||
|     -DCONFIG_ARDUHAL_LOG_COLORS=1 | ||||
|     -DOTA_DEBUG=1 | ||||
|     -DCONFIG_OPTIMIZATION_LEVEL_DEBUG=1 | ||||
|     -DCONFIG_ESP32_PANIC_PRINT_REBOOT | ||||
|     -DCONFIG_ARDUINO_OTA_READSIZE=8192 | ||||
|     -DCONFIG_PARTITION_TABLE_OFFSET=0x8000 | ||||
|     -DCONFIG_PARTITION_TABLE_MD5=y | ||||
|     -DCONFIG_APP_ROLLBACK_ENABLE=1 | ||||
|     -DSPIFFS_MAX_PARTITIONS=3 | ||||
|     -DCONFIG_SPIFFS_LOG_BLOCK_SIZE=4096 | ||||
|     -DCONFIG_SPIFFS_CACHE=y | ||||
|     -DBOOT_APP_PARTITION_OTA_0=1 | ||||
|     -DCONFIG_LOG_DEFAULT_LEVEL=3 | ||||
|      | ||||
| extra_scripts =  | ||||
|     scripts/extra_script.py | ||||
|     pre:scripts/pre_build.py     ; wird zuerst ausgeführt | ||||
|     pre:scripts/pre_spiffs.py    ; wird als zweites ausgeführt | ||||
|     pre:scripts/combine_html.py  ; wird als drittes ausgeführt | ||||
|     scripts/gzip_files.py | ||||
|     ${env:buildfs.extra_scripts} | ||||
|  | ||||
| ; Remove or comment out the targets line | ||||
| ;targets = buildfs, build | ||||
| [env:buildfs] | ||||
| extra_scripts = | ||||
|     pre:scripts/combine_html.py  ; Combine header with HTML files | ||||
|     scripts/gzip_files.py       ; Compress files for SPIFFS | ||||
|  | ||||
| ; Add a custom target to build both | ||||
| [platformio] | ||||
| default_envs = esp32dev | ||||
|  | ||||
|   | ||||
| @@ -12,7 +12,7 @@ | ||||
|  | ||||
| // Cache-Control Header definieren | ||||
| #define CACHE_CONTROL "max-age=31536000" // Cache für 1 Jahr | ||||
| #define MAX_UPLOAD_SIZE 4194304  // 4MB maximale Upload-Größe | ||||
| #define VERSION "1.0.0" | ||||
|  | ||||
| AsyncWebServer server(webserverPort); | ||||
| AsyncWebSocket ws("/ws"); | ||||
| @@ -413,6 +413,11 @@ void setupWebserver(AsyncWebServer &server) { | ||||
|         } | ||||
|     ); | ||||
|  | ||||
|     server.on("/api/version", HTTP_GET, [](AsyncWebServerRequest *request){ | ||||
|         String jsonResponse = "{\"version\": \"" VERSION "\"}"; | ||||
|         request->send(200, "application/json", jsonResponse); | ||||
|     }); | ||||
|  | ||||
|     // Fehlerbehandlung für nicht gefundene Seiten | ||||
|     server.onNotFound([](AsyncWebServerRequest *request){ | ||||
|         Serial.print("404 - Nicht gefunden: "); | ||||
| @@ -430,22 +435,50 @@ void setupWebserver(AsyncWebServer &server) { | ||||
|     Serial.println("Webserver gestartet"); | ||||
| } | ||||
|  | ||||
| // Upload-Handler für alle Datei-Uploads | ||||
| void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) { | ||||
|     if (!filename.endsWith(".bin")) { | ||||
|         request->send(400, "application/json", "{\"success\":false,\"message\":\"Invalid file type\"}"); | ||||
| void handleOTAUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) { | ||||
|     if (!index) { | ||||
|         // Start eines neuen Uploads | ||||
|         Serial.println("Update Start: " + filename); | ||||
|          | ||||
|         // Überprüfe den Dateityp basierend auf dem Dateinamen | ||||
|         bool isFirmware = filename.startsWith("filaman_"); | ||||
|         bool isWebpage = filename.startsWith("webpage_"); | ||||
|          | ||||
|         if (!isFirmware && !isWebpage) { | ||||
|             request->send(400, "application/json", "{\"message\":\"Invalid file type. File must start with 'filaman_' or 'webpage_'\"}"); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // Wähle den Update-Typ basierend auf dem Dateinamen | ||||
|         if (isWebpage) { | ||||
|             if (!Update.begin(SPIFFS.totalBytes(), U_SPIFFS)) { | ||||
|                 Update.printError(Serial); | ||||
|                 request->send(400, "application/json", "{\"message\":\"SPIFFS Update failed: " + String(Update.errorString()) + "\"}"); | ||||
|                 return; | ||||
|             } | ||||
|         } else { | ||||
|             if (!Update.begin(UPDATE_SIZE_UNKNOWN, U_FLASH)) { | ||||
|                 Update.printError(Serial); | ||||
|                 request->send(400, "application/json", "{\"message\":\"Firmware Update failed: " + String(Update.errorString()) + "\"}"); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (Update.write(data, len) != len) { | ||||
|         Update.printError(Serial); | ||||
|         request->send(400, "application/json", "{\"message\":\"Write failed: " + String(Update.errorString()) + "\"}"); | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     if (request->url() == "/update") { | ||||
|         handleOTAUpload(request, filename, index, data, len, final); | ||||
|  | ||||
|     if (final) { | ||||
|         if (!Update.end(true)) { | ||||
|             Update.printError(Serial); | ||||
|             request->send(400, "application/json", "{\"message\":\"Update failed: " + String(Update.errorString()) + "\"}"); | ||||
|             return; | ||||
|         } | ||||
|         request->send(200, "application/json", "{\"message\":\"Update successful!\", \"restart\": true}"); | ||||
|         delay(500); | ||||
|         ESP.restart(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Body-Handler für große Anfragen | ||||
| void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) { | ||||
|     // Handler für große POST-Anfragen | ||||
|     if (total > MAX_UPLOAD_SIZE) { | ||||
|         request->send(413, "application/json", "{\"success\":false,\"message\":\"File too large\"}"); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user