diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index dfe0770..0000000 --- a/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto diff --git a/.github/workflows/push-to-blledflasher.yml b/.github/workflows/push-to-blledflasher.yml new file mode 100644 index 0000000..3a5a944 --- /dev/null +++ b/.github/workflows/push-to-blledflasher.yml @@ -0,0 +1,68 @@ +name: Push Firmware to BLLED-Flasher + +on: + release: + types: [published, edited] + +jobs: + push-firmware: + runs-on: ubuntu-latest + + steps: + - name: Checkout BLLEDController-NG + uses: actions/checkout@v3 + + - name: Download .bin from current release + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const fs = require('fs'); + const owner = context.repo.owner; + const repo = context.repo.repo; + const release = context.payload.release; + const tag = release.tag_name; + + const assets = release.assets.filter(a => a.name.endsWith('.bin')); + if (assets.length === 0) { + core.setFailed("No .bin files found in release"); + return; + } + + fs.mkdirSync('firmware', { recursive: true }); + + for (const asset of assets) { + const dl = await github.rest.repos.getReleaseAsset({ + owner, + repo, + asset_id: asset.id, + headers: { Accept: 'application/octet-stream' } + }); + + fs.writeFileSync(`firmware/${asset.name}`, Buffer.from(dl.data)); + console.log(`βœ… Downloaded: ${asset.name}`); + } + + - name: Clone BLLED-Flasher repo + run: | + git clone https://x-access-token:${{ secrets.BLLED_FLASHER_TOKEN }}@github.com/softwarecrash/BLLED-Flasher.git flasher + cp firmware/*.bin flasher/firmware/ + + - name: Generate firmware.json + manifests + run: | + cd flasher + node generateRelease.js + + - name: Commit and Push to BLLED-Flasher + run: | + cd flasher + git config user.name "BLLED Release Bot" + git config user.email "actions@github.com" + git fetch origin + git add firmware/ + if git diff --cached --quiet; then + echo "βœ… Keine Γ„nderungen – kein Push." + else + git commit -m "πŸ“¦ Add firmware from release ${{ github.event.release.tag_name }}" + git push + fi diff --git a/.gitignore b/.gitignore index c503085..11a8876 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,4 @@ BLLEDController.code-workspace src/www/www.h .DS_Store **/.DS_Store -docs/firmware \ No newline at end of file +.github diff --git a/README.md b/README.md index dc23cd0..de5922f 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ The BL Led Controller is an ESP8266 / ESP32 based device that connects to your Bambulab X1,X1C,P1P Or P1S and controls the LED strip based on the state of the printer. ### Flashing and Setup -1. go to https://dutchdevelop.github.io/blledsetup/ +1. go to the [Web Flasher](https://softwarecrash.github.io/BLLED-Flasher/) 2. connect your ESP32 3. Select the Firmware build you want 4. Click on Flash diff --git a/docs/.nojekyll b/docs/.nojekyll deleted file mode 100644 index c0a9e35..0000000 --- a/docs/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -Sun May 18 11:18:13 UTC 2025 diff --git a/docs/blled.svg b/docs/blled.svg deleted file mode 100644 index 05b1a9a..0000000 --- a/docs/blled.svg +++ /dev/null @@ -1,42 +0,0 @@ - - - - diff --git a/docs/favicon.ico b/docs/favicon.ico deleted file mode 100644 index a69a720..0000000 Binary files a/docs/favicon.ico and /dev/null differ diff --git a/docs/firmware/BLLEDController_V1.0.0.nightly.170525.bin b/docs/firmware/BLLEDController_V1.0.0.nightly.170525.bin deleted file mode 100644 index 810d0e2..0000000 Binary files a/docs/firmware/BLLEDController_V1.0.0.nightly.170525.bin and /dev/null differ diff --git a/docs/firmware/BLLEDController_V1.0.0.nightly.170525.json b/docs/firmware/BLLEDController_V1.0.0.nightly.170525.json deleted file mode 100644 index b310cfa..0000000 --- a/docs/firmware/BLLEDController_V1.0.0.nightly.170525.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "BLLEDController_V1.0.0.nightly.170525", - "version": "1.0.0.nightly.170525", - "builds": [ - { - "chipFamily": "ESP32", - "parts": [ - { - "path": "BLLEDController_V1.0.0.nightly.170525.bin", - "offset": 0 - } - ] - } - ] -} \ No newline at end of file diff --git a/docs/firmware/BLLEDController_V1.0.0.nightly.180525.1.bin b/docs/firmware/BLLEDController_V1.0.0.nightly.180525.1.bin deleted file mode 100644 index e841a96..0000000 Binary files a/docs/firmware/BLLEDController_V1.0.0.nightly.180525.1.bin and /dev/null differ diff --git a/docs/firmware/BLLEDController_V1.0.0.nightly.180525.1.json b/docs/firmware/BLLEDController_V1.0.0.nightly.180525.1.json deleted file mode 100644 index a898f97..0000000 --- a/docs/firmware/BLLEDController_V1.0.0.nightly.180525.1.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "BLLEDController_V1.0.0.nightly.180525.1", - "version": "1.0.0.nightly.180525.1", - "builds": [ - { - "chipFamily": "ESP32", - "parts": [ - { - "path": "BLLEDController_V1.0.0.nightly.180525.1.bin", - "offset": 0 - } - ] - } - ] -} \ No newline at end of file diff --git a/docs/firmware/firmware.json b/docs/firmware/firmware.json deleted file mode 100644 index 8ed1294..0000000 --- a/docs/firmware/firmware.json +++ /dev/null @@ -1,12 +0,0 @@ -[ - { - "version": "1.0.0.nightly.170525", - "prerelease": true, - "file": "BLLEDController_V1.0.0.nightly.170525.bin" - }, - { - "version": "1.0.0.nightly.180525.1", - "prerelease": true, - "file": "BLLEDController_V1.0.0.nightly.180525.1.bin" - } -] \ No newline at end of file diff --git a/docs/firmware/last_update.txt b/docs/firmware/last_update.txt deleted file mode 100644 index fc521ca..0000000 --- a/docs/firmware/last_update.txt +++ /dev/null @@ -1 +0,0 @@ -Updated at Sun May 18 16:16:20 UTC 2025 diff --git a/docs/firmware/readme.md b/docs/firmware/readme.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs/generateRelease.js b/docs/generateRelease.js deleted file mode 100644 index 6e36a29..0000000 --- a/docs/generateRelease.js +++ /dev/null @@ -1,51 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -const firmwareDir = path.resolve(__dirname, 'firmware'); -const binFiles = fs.readdirSync(firmwareDir).filter(f => f.endsWith('.bin')); - -if (binFiles.length === 0) { - console.log('❌ No .bin files found in firmware folder.'); - process.exit(1); -} - -const firmwareList = []; - -for (const file of binFiles) { - const versionMatch = file.match(/_V?([\w.\-]+)\.bin$/); - const version = versionMatch ? versionMatch[1] : 'unknown'; - const isPre = file.toLowerCase().includes('nightly') || file.toLowerCase().includes('beta'); - - // πŸ‘‡ Add entry to firmware.json - firmwareList.push({ - version, - prerelease: isPre, - file - }); - - // πŸ‘‡ Create ESP Web Tools Manifest (merged .bin format) - const manifest = { - name: file.replace(/\.bin$/, ''), - version, - builds: [ - { - chipFamily: "ESP32", - parts: [ - { - path: file, - offset: 0 - } - ] - } - ] - }; - - const manifestPath = path.join(firmwareDir, file.replace(/\.bin$/, '.json')); - fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2)); - console.log(`βœ… Created manifest: ${manifestPath}`); -} - -// πŸ‘‡ Write firmware.json (for dropdown use in UI) -const firmwareJsonPath = path.join(firmwareDir, 'firmware.json'); -fs.writeFileSync(firmwareJsonPath, JSON.stringify(firmwareList, null, 2)); -console.log(`βœ… Created firmware list: ${firmwareJsonPath}`); diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 090b53e..0000000 --- a/docs/index.html +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - - BLLEDController-NG WebFlasher - - - - - - - -
- - -
-

Select a firmware version below and click Connect to flash your device.

- - - - - - -

-
- - -
- - - - - - - diff --git a/docs/particleCanvas.js b/docs/particleCanvas.js deleted file mode 100644 index 03dd4a9..0000000 --- a/docs/particleCanvas.js +++ /dev/null @@ -1,94 +0,0 @@ - const canvas = document.getElementById('particleCanvas'); - const ctx = canvas.getContext('2d'); - canvas.width = window.innerWidth; - canvas.height = window.innerHeight; - - let particlesArray = []; - const numberOfParticles = 100; - - class Particle { - constructor(x, y, directionX, directionY, size, color) { - this.x = x; - this.y = y; - this.directionX = directionX; - this.directionY = directionY; - this.size = size; - this.color = color; - } - draw() { - ctx.beginPath(); - ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2, false); - ctx.fillStyle = this.color; - ctx.fill(); - } - - - update() { - if (this.x + this.size > canvas.width || this.x - this.size < 0) { - this.directionX = -this.directionX; - } - - if (this.y + this.size > canvas.height || this.y - this.size < 0) { - this.directionY = -this.directionY; - } - - this.x += this.directionX; - this.y += this.directionY; - - this.draw(); - } - } - - function init() { - particlesArray = []; - for (let i = 0; i < numberOfParticles; i++) { - let size = Math.random() * 5 + 1; - let x = Math.random() * (canvas.width - size * 2) + size; - let y = Math.random() * (canvas.height - size * 2) + size; - let directionX = (Math.random() * 0.5) - 0.25; - let directionY = (Math.random() * 0.5) - 0.25; - let color = 'rgba(255, 255, 255, 0.8)'; - - particlesArray.push(new Particle(x, y, directionX, directionY, size, color)); - } - } - - function connect() { - let opacityValue = 1; - for (let a = 0; a < particlesArray.length; a++) { - for (let b = a; b < particlesArray.length; b++) { - let distance = ((particlesArray[a].x - particlesArray[b].x) * (particlesArray[a].x - particlesArray[b].x)) - + ((particlesArray[a].y - particlesArray[b].y) * (particlesArray[a].y - particlesArray[b].y)); - - if (distance < (canvas.width / 7) * (canvas.height / 7)) { - opacityValue = 1 - (distance / 20000); - ctx.strokeStyle = 'rgba(255, 255, 255,' + opacityValue + ')'; - ctx.lineWidth = 1; - ctx.beginPath(); - ctx.moveTo(particlesArray[a].x, particlesArray[a].y); - ctx.lineTo(particlesArray[b].x, particlesArray[b].y); - ctx.stroke(); - } - } - } - } - - function animate() { - ctx.clearRect(0, 0, canvas.width, canvas.height); - - for (let i = 0; i < particlesArray.length; i++) { - particlesArray[i].update(); - } - - connect(); - requestAnimationFrame(animate); - } - - window.addEventListener('resize', () => { - canvas.width = window.innerWidth; - canvas.height = window.innerHeight; - init(); - }); - - init(); - animate(); \ No newline at end of file diff --git a/docs/script.js b/docs/script.js deleted file mode 100644 index 32f2152..0000000 --- a/docs/script.js +++ /dev/null @@ -1,39 +0,0 @@ -document.addEventListener("DOMContentLoaded", async () => { - const firmwareSelect = document.getElementById("firmwareSelect"); - const flashButton = document.getElementById("flashButton"); - const basePath = window.location.pathname.replace(/\/[^/]*$/, ''); - const manifestBase = window.location.origin + basePath + "/firmware/"; - - try { - const response = await fetch("firmware/firmware.json"); - const firmwares = await response.json(); - - if (!Array.isArray(firmwares)) throw new Error("Invalid JSON structure"); - - // Sortiere nach neuester Version oben (optional) - firmwares.sort((a, b) => b.version.localeCompare(a.version, undefined, { numeric: true, sensitivity: 'base' })); - - for (const fw of firmwares) { - const opt = document.createElement("option"); - const label = `${fw.version}${fw.prerelease ? " (pre)" : ""}`; - opt.value = fw.file; - opt.textContent = label; - firmwareSelect.appendChild(opt); - } - - firmwareSelect.addEventListener("change", () => { - const selected = firmwareSelect.value; - if (selected) { - flashButton.setAttribute("manifest", manifestBase + selected.replace(/\.bin$/, ".json")); - flashButton.setAttribute("enabled", ""); - } else { - flashButton.removeAttribute("manifest"); - flashButton.removeAttribute("enabled"); - } - }); - } catch (err) { - console.error("Fehler beim Laden der Firmware-Liste:", err); - const status = document.getElementById("status"); - if (status) status.textContent = "Fehler beim Laden der Firmware-Dateien."; - } -}); \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 7ab13cc..fc18a31 100644 --- a/platformio.ini +++ b/platformio.ini @@ -11,7 +11,7 @@ [env:esp32dev] custom_project_name = BLLEDController custom_project_codename = Balder -custom_version = 1.0.0.nightly.180525.1 ; for github release name the release VX.Y.Z X=(Incerase when Modifications oder new functions Break the API/webUI) Y=(Incerase for add oder modify changes that not breake the API/webUI until X incearase) Z=(Incerase for bugfix releases until minor is incerase) +custom_version = 1.0.0.nightly.250525.1 ; for github release name the release VX.Y.Z X=(Incerase when Modifications oder new functions Break the API/webUI) Y=(Incerase for add oder modify changes that not breake the API/webUI until X incearase) Z=(Incerase for bugfix releases until minor is incerase) platform = espressif32 board = esp32dev framework = arduino @@ -30,4 +30,4 @@ lib_deps = luc-github/ESP32SSDP@1.2.1 ESP32Async/AsyncTCP ESP32Async/ESPAsyncWebServer - mathieucarbou/MycilaWebSerial@^8.0.0 \ No newline at end of file + mathieucarbou/MycilaWebSerial@^8.1.1 \ No newline at end of file diff --git a/src/blled/AutoGrowBufferStream.h b/src/blled/AutoGrowBufferStream.h index 95c2fd0..6589de9 100644 --- a/src/blled/AutoGrowBufferStream.h +++ b/src/blled/AutoGrowBufferStream.h @@ -29,7 +29,7 @@ class AutoGrowBufferStream : public Stream if (this->_len + 1 > this->buffer_size) { auto tmp = (char*)realloc(this->_buffer, this->buffer_size + BUFFER_INCREMENTS); if (tmp == NULL) { - Serial.println(F("Failed to grow buffer")); + LogSerial.println(F("Failed to grow buffer")); return 0; } this->_buffer = tmp; diff --git a/src/blled/filesystem.h b/src/blled/filesystem.h index abe3275..f1cf177 100644 --- a/src/blled/filesystem.h +++ b/src/blled/filesystem.h @@ -28,7 +28,7 @@ char *generateRandomString(int length) void saveFileSystem() { - Serial.println(F("Saving config")); + LogSerial.println(F("Saving config")); JsonDocument json; json["ssid"] = globalVariables.SSID; @@ -124,17 +124,17 @@ void saveFileSystem() File configFile = LittleFS.open(configPath, "w"); if (!configFile) { - Serial.println(F("Failed to save config")); + LogSerial.println(F("Failed to save config")); return; } serializeJson(json, configFile); configFile.close(); - Serial.println(F("Config Saved")); + LogSerial.println(F("Config Saved")); } void loadFileSystem() { - Serial.println(F("Loading config")); + LogSerial.println(F("Loading config")); File configFile; int attempts = 0; @@ -146,16 +146,16 @@ void loadFileSystem() break; } attempts++; - Serial.println(F("Failed to open config file, retrying..")); + LogSerial.println(F("Failed to open config file, retrying..")); delay(2000); } if (!configFile) { - Serial.print(F("Failed to open config file after ")); - Serial.print(attempts); - Serial.println(F(" retries")); + LogSerial.print(F("Failed to open config file after ")); + LogSerial.print(attempts); + LogSerial.println(F(" retries")); - Serial.println(F("Clearing config")); + LogSerial.println(F("Clearing config")); // LittleFS.remove(configPath); saveFileSystem(); return; @@ -222,15 +222,15 @@ void loadFileSystem() printerConfig.frontCoverRGB = hex2rgb(json["frontCoverRGB"], json["frontCoverWW"], json["frontCoverCW"]); printerConfig.nozzleTempRGB = hex2rgb(json["nozzleTempRGB"], json["nozzleTempWW"], json["nozzleTempCW"]); printerConfig.bedTempRGB = hex2rgb(json["bedTempRGB"], json["bedTempWW"], json["bedTempCW"]); - Serial.println(F("Loaded config")); + LogSerial.println(F("Loaded config")); } else { - Serial.println(F("Failed loading config")); - Serial.println(F("Clearing config")); + LogSerial.println(F("Failed loading config")); + LogSerial.println(F("Clearing config")); LittleFS.remove(configPath); - // Serial.println(F("Generating new password")); + // LogSerial.println(F("Generating new password")); // char* pw = generateRandomString(8); // strcpy(printerConfig.webpagePassword, pw); } @@ -240,7 +240,7 @@ void loadFileSystem() void deleteFileSystem() { - Serial.println(F("Deleting LittleFS")); + LogSerial.println(F("Deleting LittleFS")); LittleFS.remove(configPath); } @@ -251,17 +251,17 @@ bool hasFileSystem() void setupFileSystem() { - Serial.println(F("Mounting LittleFS")); + LogSerial.println(F("Mounting LittleFS")); if (!LittleFS.begin()) { - Serial.println(F("Failed to mount LittleFS")); + LogSerial.println(F("Failed to mount LittleFS")); LittleFS.format(); - Serial.println(F("Formatting LittleFS")); - Serial.println(F("Restarting Device")); + LogSerial.println(F("Formatting LittleFS")); + LogSerial.println(F("Restarting Device")); delay(1000); ESP.restart(); } - Serial.println(F("Mounted LittleFS")); + LogSerial.println(F("Mounted LittleFS")); }; #endif \ No newline at end of file diff --git a/src/blled/leds.h b/src/blled/leds.h index 76dc7e2..36ae1f8 100644 --- a/src/blled/leds.h +++ b/src/blled/leds.h @@ -10,6 +10,15 @@ const int bluePin = 21; const int warmPin = 22; const int coldPin = 23; +const int redChannel = 0; +const int greenChannel = 1; +const int blueChannel = 2; +const int warmChannel = 3; +const int coldChannel = 4; + +const int pwmFreq = 5000; +const int pwmResolution = 8; // 8-bit PWM = 0-255 + int currentRed = 0; int currentGreen = 0; int currentBlue = 0; @@ -19,29 +28,33 @@ int currentCold = 0; unsigned long lastUpdatems = 0; unsigned long oldms = 0; -COLOR hex2rgb(String hex, short ww_value = 0, short cw_value = 0) { +COLOR hex2rgb(String hex, short ww_value = 0, short cw_value = 0) +{ COLOR color; long hexcolor; strcpy(color.RGBhex, hex.c_str()); - if(hex.charAt(0) == '#') { - hex.remove(0,1); + if (hex.charAt(0) == '#') + { + hex.remove(0, 1); } - while(hex.length() != 6) { + while (hex.length() != 6) + { hex += "0"; } hexcolor = strtol(hex.c_str(), NULL, 16); color.r = (hexcolor & 0xFF0000) >> 16; color.g = (hexcolor & 0x00FF00) >> 8; - color.b = (hexcolor & 0x0000FF); + color.b = (hexcolor & 0x0000FF); color.ww = ww_value; color.cw = cw_value; - + return color; } -void tweenToColor(int targetRed, int targetGreen, int targetBlue, int targetWarm, int targetCold, int duration = 500) { +void tweenToColor(int targetRed, int targetGreen, int targetBlue, int targetWarm, int targetCold, int duration = 500) +{ - float brightness = (float)printerConfig.brightness/100.0; + float brightness = (float)printerConfig.brightness / 100.0; int brightenedRed = round(targetRed * brightness); int brightenedGreen = round(targetGreen * brightness); @@ -49,22 +62,24 @@ void tweenToColor(int targetRed, int targetGreen, int targetBlue, int targetWarm int brightenedWarm = round(targetWarm * brightness); int brightenedCold = round(targetCold * brightness); - if (brightenedRed == currentRed && brightenedGreen == currentGreen && brightenedBlue == currentBlue && brightenedWarm == currentWarm && brightenedCold == currentCold){ + if (brightenedRed == currentRed && brightenedGreen == currentGreen && brightenedBlue == currentBlue && brightenedWarm == currentWarm && brightenedCold == currentCold) + { // Already set to the requested color - if (printerConfig.debuging){ - Serial.print(F("LEDS already at color: (")); - Serial.print(currentRed); - Serial.print(F(", ")); - Serial.print(currentGreen); - Serial.print(F(", ")); - Serial.print(currentBlue); - Serial.print(F(", ")); - Serial.print(currentWarm); - Serial.print(F(", ")); - Serial.print(currentCold); - Serial.print(F(" Brightness: ")); - Serial.print(printerConfig.brightness); - Serial.println(F(")")); + if (printerConfig.debuging) + { + LogSerial.print(F("LEDS already at color: (")); + LogSerial.print(currentRed); + LogSerial.print(F(", ")); + LogSerial.print(currentGreen); + LogSerial.print(F(", ")); + LogSerial.print(currentBlue); + LogSerial.print(F(", ")); + LogSerial.print(currentWarm); + LogSerial.print(F(", ")); + LogSerial.print(currentCold); + LogSerial.print(F(" Brightness: ")); + LogSerial.print(printerConfig.brightness); + LogSerial.println(F(")")); }; return; } @@ -75,18 +90,19 @@ void tweenToColor(int targetRed, int targetGreen, int targetBlue, int targetWarm int warmStep = (brightenedWarm - currentWarm) / 255; int coldStep = (brightenedCold - currentCold) / 255; - for (int i = 0; i < 256; i++) { + for (int i = 0; i < 256; i++) + { currentRed += redStep; currentGreen += greenStep; currentBlue += blueStep; currentWarm += warmStep; currentCold += coldStep; - analogWrite(redPin, currentRed); - analogWrite(greenPin, currentGreen); - analogWrite(bluePin, currentBlue); - analogWrite(warmPin, currentWarm); - analogWrite(coldPin, currentCold); + ledcWrite(redChannel, currentRed); + ledcWrite(greenChannel, currentGreen); + ledcWrite(blueChannel, currentBlue); + ledcWrite(warmChannel, currentWarm); + ledcWrite(coldChannel, currentCold); delay(stepTime); } @@ -96,25 +112,28 @@ void tweenToColor(int targetRed, int targetGreen, int targetBlue, int targetWarm currentWarm = brightenedWarm; currentCold = brightenedCold; - analogWrite(redPin, currentRed); - analogWrite(greenPin, currentGreen); - analogWrite(bluePin, currentBlue); - analogWrite(warmPin, currentWarm); - analogWrite(coldPin, currentCold); + ledcWrite(redChannel, currentRed); + ledcWrite(greenChannel, currentGreen); + ledcWrite(blueChannel, currentBlue); + ledcWrite(warmChannel, currentWarm); + ledcWrite(coldChannel, currentCold); } -//Helper functions to allow changes colors by using a string or integer hex code -void tweenToColor(COLOR targetcolor) { +// Helper functions to allow changes colors by using a string or integer hex code +void tweenToColor(COLOR targetcolor) +{ tweenToColor(targetcolor.r, targetcolor.g, targetcolor.b, targetcolor.ww, targetcolor.cw); } -//Example: tweenToColor("#33FD67") -void tweenToColor(String strTargetColor, short ww_value = 0, short cw_value = 0) { +// Example: tweenToColor("#33FD67") +void tweenToColor(String strTargetColor, short ww_value = 0, short cw_value = 0) +{ COLOR targetcolor; targetcolor = hex2rgb(strTargetColor, ww_value, cw_value); tweenToColor(targetcolor.r, targetcolor.g, targetcolor.b, targetcolor.ww, targetcolor.cw); } -//Example: tweenToColor(0xFFACA5) -void tweenToColor(int hexValue, short ww_value = 0, short cw_value = 0) { +// Example: tweenToColor(0xFFACA5) +void tweenToColor(int hexValue, short ww_value = 0, short cw_value = 0) +{ COLOR targetcolor; targetcolor.r = ((hexValue >> 16) & 0xFF) / 255.0; targetcolor.g = ((hexValue >> 8) & 0xFF) / 255.0; @@ -126,32 +145,38 @@ void tweenToColor(int hexValue, short ww_value = 0, short cw_value = 0) { float hue = 0.0; -void RGBCycle() { - if (printerConfig.discoMode == false) { - //Skip changing colors if RGB Mode not enabled +void RGBCycle() +{ + if (printerConfig.discoMode == false) + { + // Skip changing colors if RGB Mode not enabled printerConfig.discoMode_update = true; return; } - if(printerConfig.discoMode_update){ + if (printerConfig.discoMode_update) + { printerConfig.discoMode_update = false; - if (printerConfig.debugingchange){ - Serial.print(F("[")); - Serial.print(millis()); - Serial.print(F("]")); - Serial.println(F(" ** RGB Cycle Mode **")); + if (printerConfig.debugingchange) + { + LogSerial.print(F("[")); + LogSerial.print(millis()); + LogSerial.print(F("]")); + LogSerial.println(F(" ** RGB Cycle Mode **")); }; } - if (printerVariables.online == false) { - analogWrite(redPin, 0); - analogWrite(greenPin, 0); - analogWrite(bluePin, 0); - analogWrite(warmPin, 0); - analogWrite(coldPin, 0); + if (printerVariables.online == false) + { + ledcWrite(redChannel, 0); + ledcWrite(greenChannel, 0); + ledcWrite(blueChannel, 0); + ledcWrite(warmChannel, 0); + ledcWrite(coldChannel, 0); return; } hue += 0.1; - if (hue > 360.0) { + if (hue > 360.0) + { hue = 0.0; } @@ -161,38 +186,42 @@ void RGBCycle() { currentWarm = 0; currentCold = 0; - //Need to add code so it adjusts to set brightness level + // Need to add code so it adjusts to set brightness level - analogWrite(redPin, currentRed); - analogWrite(greenPin, currentGreen); - analogWrite(bluePin, currentBlue); - analogWrite(warmPin, currentWarm); - analogWrite(coldPin, currentCold); + ledcWrite(redChannel, currentRed); + ledcWrite(greenChannel, currentGreen); + ledcWrite(blueChannel, currentBlue); + ledcWrite(warmChannel, currentWarm); + ledcWrite(coldChannel, currentCold); } -void printLogs(String Desc, COLOR thisColor){ - if (printerConfig.debuging || printerConfig.debugingchange){ - Serial.print(Desc); - Serial.print(F(" - Turning LEDs to: ")); - if((thisColor.r + thisColor.g + thisColor.b + thisColor.ww + thisColor.cw) == 0){ - Serial.println(F(" OFF")); +void printLogs(String Desc, COLOR thisColor) +{ + if (printerConfig.debuging || printerConfig.debugingchange) + { + LogSerial.print(Desc); + LogSerial.print(F(" - Turning LEDs to: ")); + if ((thisColor.r + thisColor.g + thisColor.b + thisColor.ww + thisColor.cw) == 0) + { + LogSerial.println(F(" OFF")); return; } - Serial.print(F(" r:")); - Serial.print(thisColor.r); - Serial.print(F(" g:")); - Serial.print(thisColor.g); - Serial.print(F(" b:")); - Serial.print(thisColor.b); - Serial.print(F(" ww:")); - Serial.print(thisColor.ww); - Serial.print(F(" cw:")); - Serial.print(thisColor.cw); - Serial.print(F(" Brightness: ")); - Serial.println(printerConfig.brightness); + LogSerial.print(F(" r:")); + LogSerial.print(thisColor.r); + LogSerial.print(F(" g:")); + LogSerial.print(thisColor.g); + LogSerial.print(F(" b:")); + LogSerial.print(thisColor.b); + LogSerial.print(F(" ww:")); + LogSerial.print(thisColor.ww); + LogSerial.print(F(" cw:")); + LogSerial.print(thisColor.cw); + LogSerial.print(F(" Brightness: ")); + LogSerial.println(printerConfig.brightness); }; } -void printLogs(String Desc, short r, short g, short b, short ww, short cw){ +void printLogs(String Desc, short r, short g, short b, short ww, short cw) +{ COLOR tempColor; tempColor.r = r; tempColor.g = g; @@ -201,359 +230,414 @@ void printLogs(String Desc, short r, short g, short b, short ww, short cw){ tempColor.cw = cw; printLogs(Desc, tempColor); } -void updateleds(){ - //Maintenance Mode - White lights on regardless of printer power, WiFi or MQTT connection - //priortised over Wifi Strength Display or Custom TEST color - if (printerConfig.maintMode && printerConfig.maintMode_update){ - tweenToColor(0,0,0,255,255); //WHITE +void updateleds() +{ + // Maintenance Mode - White lights on regardless of printer power, WiFi or MQTT connection + // priortised over Wifi Strength Display or Custom TEST color + if (printerConfig.maintMode && printerConfig.maintMode_update) + { + tweenToColor(0, 0, 0, 255, 255); // WHITE printerConfig.maintMode_update = false; - printLogs("Maintenance Mode", 0,0,0,255,255); - Serial.print(F("[")); - Serial.print(millis()); - Serial.print(F("]")); - Serial.println(F(" ** Maintenance Mode **")); + printLogs("Maintenance Mode", 0, 0, 0, 255, 255); + LogSerial.print(F("[")); + LogSerial.print(millis()); + LogSerial.print(F("]")); + LogSerial.println(F(" ** Maintenance Mode **")); return; } - //Use LED to show WIFI Strength (enabled via Setup Webpage) - if (printerConfig.debugwifi){ + // Use LED to show WIFI Strength (enabled via Setup Webpage) + if (printerConfig.debugwifi) + { //<=-50 dBm Green, <= -60 dBm LightGreen, <= -70 dBm Yellow, <= -80 dBm Orange, >80 Red - if (WiFi.status() == WL_CONNECTED){ + if (WiFi.status() == WL_CONNECTED) + { long wifiNow = WiFi.RSSI(); - if (printerConfig.debugingchange){ - Serial.print(F("WiFi Strength Visialisation, display LEDs for: ")); - Serial.println(wifiNow); + if (printerConfig.debugingchange) + { + LogSerial.print(F("WiFi Strength Visialisation, display LEDs for: ")); + LogSerial.println(wifiNow); } - if (wifiNow >= -50) tweenToColor(0,255,0,0,0); //GREEN - else if (wifiNow >= -60) tweenToColor(128,255,0,0,0); //LIGHTGREEN - else if (wifiNow >= -70) tweenToColor(255,255,0,0,0); //YELLOW - else if (wifiNow >= -80) tweenToColor(255,128,0,0,0); //ORANGE - else if (wifiNow < -80) tweenToColor(255,0,0,0,0); //RED - else tweenToColor(0,0,255,0,0); //BLUE + if (wifiNow >= -50) + tweenToColor(0, 255, 0, 0, 0); // GREEN + else if (wifiNow >= -60) + tweenToColor(128, 255, 0, 0, 0); // LIGHTGREEN + else if (wifiNow >= -70) + tweenToColor(255, 255, 0, 0, 0); // YELLOW + else if (wifiNow >= -80) + tweenToColor(255, 128, 0, 0, 0); // ORANGE + else if (wifiNow < -80) + tweenToColor(255, 0, 0, 0, 0); // RED + else + tweenToColor(0, 0, 255, 0, 0); // BLUE }; return; } - //TEST Color Enabled - LED ON regardless of printer state - if (printerConfig.testcolorEnabled && printerConfig.testcolor_update){ - tweenToColor(printerConfig.testColor); //Variable Test Color + // TEST Color Enabled - LED ON regardless of printer state + if (printerConfig.testcolorEnabled && printerConfig.testcolor_update) + { + tweenToColor(printerConfig.testColor); // Variable Test Color printLogs("LED Test ON", printerConfig.testColor); - Serial.print(F("[")); - Serial.print(millis()); - Serial.print(F("]")); - Serial.println(F(" ** Test Color Mode **")); + LogSerial.print(F("[")); + LogSerial.print(millis()); + LogSerial.print(F("]")); + LogSerial.println(F(" ** Test Color Mode **")); printerConfig.testcolor_update = false; return; } - //From here the BBLP status sets the colors - if (printerConfig.debuging == true){ - Serial.println(F("Updating LEDs")); + // From here the BBLP status sets the colors + if (printerConfig.debuging == true) + { + LogSerial.println(F("Updating LEDs")); - Serial.println(printerVariables.stage); - Serial.println(printerVariables.gcodeState); - Serial.println(printerVariables.printerledstate); - Serial.println(printerVariables.hmsstate); - Serial.println(printerVariables.parsedHMSlevel); + LogSerial.println(printerVariables.stage); + LogSerial.println(printerVariables.gcodeState); + LogSerial.println(printerVariables.printerledstate); + LogSerial.println(printerVariables.hmsstate); + LogSerial.println(printerVariables.parsedHMSlevel); } - //Initial Boot - if (printerVariables.initalisedLEDs == false) { - printerVariables.initalisedLEDs = true; //Run once per boot - printerConfig.inactivityStartms = millis(); //restart idle timer + // Initial Boot + if (printerVariables.initalisedLEDs == false) + { + printerVariables.initalisedLEDs = true; // Run once per boot + printerConfig.inactivityStartms = millis(); // restart idle timer printerConfig.isIdleOFFActive = false; printerVariables.waitingForDoor = false; printerConfig.finish_check = false; printerVariables.lastdoorClosems = millis(); - Serial.println(F("Initial Boot")); + LogSerial.println(F("Initial Boot")); return; } - if(printerConfig.testcolorEnabled || printerConfig.maintMode || printerConfig.debugwifi || printerConfig.discoMode){ - //Skip trying to set a color as it's in one of the override states + if (printerConfig.testcolorEnabled || printerConfig.maintMode || printerConfig.debugwifi || printerConfig.discoMode) + { + // Skip trying to set a color as it's in one of the override states return; } - //TOGGLE LIGHTS via DOOR - //If door is closed twice in 6 seconds, it will flip the state of the lights - if (printerVariables.doorSwitchTriggered == true){ - if (printerConfig.debugingchange){ - Serial.print(F("Door closed twice within 6 seconds - Toggling LEDs to ")); + // TOGGLE LIGHTS via DOOR + // If door is closed twice in 6 seconds, it will flip the state of the lights + if (printerVariables.doorSwitchTriggered == true) + { + if (printerConfig.debugingchange) + { + LogSerial.print(F("Door closed twice within 6 seconds - Toggling LEDs to ")); } - if(currentWarm == 0 && currentCold == 0) + if (currentWarm == 0 && currentCold == 0) { - tweenToColor(0,0,0,255,255); //WHITE - if (printerConfig.debuging || printerConfig.debugingchange) { - Serial.println(F("ON")); + tweenToColor(0, 0, 0, 255, 255); // WHITE + if (printerConfig.debuging || printerConfig.debugingchange) + { + LogSerial.println(F("ON")); } printerConfig.isIdleOFFActive = false; } else { - tweenToColor(0,0,0,0,0); //OFF - //Shortcut to idle state - note: light will go back on immediately if there is an MQTT change of any sort + tweenToColor(0, 0, 0, 0, 0); // OFF + // Shortcut to idle state - note: light will go back on immediately if there is an MQTT change of any sort printerConfig.isIdleOFFActive = true; - printerConfig.inactivityStartms = (millis()-printerConfig.inactivityTimeOut); - if (printerConfig.debuging || printerConfig.debugingchange) { - Serial.println(F("OFF")); + printerConfig.inactivityStartms = (millis() - printerConfig.inactivityTimeOut); + if (printerConfig.debuging || printerConfig.debugingchange) + { + LogSerial.println(F("OFF")); } } printerVariables.doorSwitchTriggered = false; return; } - - //RED -- RED -- RED -- RED + + // RED -- RED -- RED -- RED // allow errordetection to turn ledstrip red - if (printerConfig.errordetection == true){ + if (printerConfig.errordetection == true) + { - //Fillament runout - if (printerVariables.stage == 6 || printerVariables.overridestage == 6){ - tweenToColor(printerConfig.filamentRunoutRGB); //Customisable - Default is RED + // Fillament runout + if (printerVariables.stage == 6 || printerVariables.overridestage == 6) + { + tweenToColor(printerConfig.filamentRunoutRGB); // Customisable - Default is RED printLogs("Stage 6, FILAMENT RUNOUT", printerConfig.filamentRunoutRGB); return; }; - //Front Cover Removed - if (printerVariables.stage == 17 || printerVariables.overridestage == 17){ - tweenToColor(printerConfig.frontCoverRGB); //Customisable - Default is RED + // Front Cover Removed + if (printerVariables.stage == 17 || printerVariables.overridestage == 17) + { + tweenToColor(printerConfig.frontCoverRGB); // Customisable - Default is RED printLogs("Stage 17, FRONT COVER REMOVED", printerConfig.frontCoverRGB); return; }; - //Nozzle Temp fail - if (printerVariables.stage == 20 || printerVariables.overridestage == 20){ - tweenToColor(printerConfig.nozzleTempRGB); //Customisable - Default is RED + // Nozzle Temp fail + if (printerVariables.stage == 20 || printerVariables.overridestage == 20) + { + tweenToColor(printerConfig.nozzleTempRGB); // Customisable - Default is RED printLogs("Stage 20, NOZZLE TEMP FAIL", printerConfig.nozzleTempRGB); return; }; - //Bed Temp Fail - if (printerVariables.stage == 21 || printerVariables.overridestage == 21){ - tweenToColor(printerConfig.bedTempRGB); //Customisable - Default is RED + // Bed Temp Fail + if (printerVariables.stage == 21 || printerVariables.overridestage == 21) + { + tweenToColor(printerConfig.bedTempRGB); // Customisable - Default is RED printLogs("Stage 21, BED TEMP FAIL", printerConfig.bedTempRGB); return; }; - //SERIOUS HMS state - if (printerVariables.parsedHMSlevel == "Serious"){ - tweenToColor(printerConfig.hmsSeriousRGB); //Customisable - Default is RED - Serial.print(F("HMS SERIOUS Severity ")); - Serial.print(F("Error Code: ")); - Serial.printf("%016llX\n", printerVariables.parsedHMScode); + // SERIOUS HMS state + if (printerVariables.parsedHMSlevel == "Serious") + { + tweenToColor(printerConfig.hmsSeriousRGB); // Customisable - Default is RED + LogSerial.print(F("HMS SERIOUS Severity ")); + LogSerial.print(F("Error Code: ")); + LogSerial.printf("%016llX\n", printerVariables.parsedHMScode); printLogs("PROBLEM", printerConfig.hmsSeriousRGB); return; }; - //FATAL HMS state - if (printerVariables.parsedHMSlevel == "Fatal"){ - tweenToColor(printerConfig.hmsFatalRGB); //Customisable - Default is RED - Serial.print(F("HMS FATAL Severity ")); - Serial.print(F("Error Code: ")); - Serial.printf("%016llX\n", printerVariables.parsedHMScode); + // FATAL HMS state + if (printerVariables.parsedHMSlevel == "Fatal") + { + tweenToColor(printerConfig.hmsFatalRGB); // Customisable - Default is RED + LogSerial.print(F("HMS FATAL Severity ")); + LogSerial.print(F("Error Code: ")); + LogSerial.printf("%016llX\n", printerVariables.parsedHMScode); printLogs("PROBLEM", printerConfig.hmsFatalRGB); return; }; }; - //BLUE -- BLUE -- BLUE -- BLUE - + // BLUE -- BLUE -- BLUE -- BLUE + // Pause (by user or via Gcode) - if ((printerVariables.stage == 16 || printerVariables.stage == 30) || printerVariables.gcodeState == "PAUSE"){ - tweenToColor(printerConfig.pauseRGB); //Customisable - Default is BLUE + if ((printerVariables.stage == 16 || printerVariables.stage == 30) || printerVariables.gcodeState == "PAUSE") + { + tweenToColor(printerConfig.pauseRGB); // Customisable - Default is BLUE printLogs("Stage 16, gcodeState pause, PAUSED", printerConfig.pauseRGB); return; } - //First Layer Error PAUSED - if (printerVariables.stage == 34){ - tweenToColor(printerConfig.firstlayerRGB); //Customisable - Default is BLUE + // First Layer Error PAUSED + if (printerVariables.stage == 34) + { + tweenToColor(printerConfig.firstlayerRGB); // Customisable - Default is BLUE printLogs("Stage 34, FIRST LAYER ERROR, PAUSED", printerConfig.firstlayerRGB); return; } - //Nozzle Clog PAUSED - if (printerVariables.stage == 35){ - tweenToColor(printerConfig.nozzleclogRGB); //Customisable - Default is BLUE + // Nozzle Clog PAUSED + if (printerVariables.stage == 35) + { + tweenToColor(printerConfig.nozzleclogRGB); // Customisable - Default is BLUE printLogs("Stage 35, NOZZLE CLOG, PAUSED", printerConfig.nozzleclogRGB); return; } - //OFF -- OFF -- OFF -- OFF + // OFF -- OFF -- OFF -- OFF - //printer offline and MQTT disconnect more than 5 seconds. - if (printerVariables.online == false && (millis() - printerVariables.disconnectMQTTms) >= 5000){ - tweenToColor(0,0,0,0,0); //OFF - printLogs("Printer offline", 0,0,0,0,0); + // printer offline and MQTT disconnect more than 5 seconds. + if (printerVariables.online == false && (millis() - printerVariables.disconnectMQTTms) >= 5000) + { + tweenToColor(0, 0, 0, 0, 0); // OFF + printLogs("Printer offline", 0, 0, 0, 0, 0); return; } // replicate printer behaviour OFF - if (printerConfig.replicatestate && printerConfig.replicate_update && printerVariables.printerledstate == false){ - tweenToColor(0,0,0,0,0); //OFF - printLogs("LED Replication OFF", 0,0,0,0,0); + if (printerConfig.replicatestate && printerConfig.replicate_update && printerVariables.printerledstate == false) + { + tweenToColor(0, 0, 0, 0, 0); // OFF + printLogs("LED Replication OFF", 0, 0, 0, 0, 0); printerConfig.replicate_update = false; return; } - //Cleaning nozzle - if (printerVariables.stage == 14){ - tweenToColor(printerConfig.stage14Color); //Customisable - Default is OFF + // Cleaning nozzle + if (printerVariables.stage == 14) + { + tweenToColor(printerConfig.stage14Color); // Customisable - Default is OFF printLogs("Stage 14, CLEANING NOZZLE", printerConfig.stage14Color); return; } - //Auto Bed Leveling - if (printerVariables.stage == 1){ - tweenToColor(printerConfig.stage1Color); //Customisable - Default is OFF + // Auto Bed Leveling + if (printerVariables.stage == 1) + { + tweenToColor(printerConfig.stage1Color); // Customisable - Default is OFF printLogs("Stage 1, BED LEVELING", printerConfig.stage1Color); return; } - //Calibrating Extrusion - if (printerVariables.stage == 8){ - tweenToColor(printerConfig.stage8Color); //Customisable - Default is OFF + // Calibrating Extrusion + if (printerVariables.stage == 8) + { + tweenToColor(printerConfig.stage8Color); // Customisable - Default is OFF printLogs("Stage 8, CALIBRATING EXTRUSION", printerConfig.stage8Color); return; } - //Scaning surface - if (printerVariables.stage == 9){ - tweenToColor(printerConfig.stage9Color); //Customisable - Default is OFF + // Scaning surface + if (printerVariables.stage == 9) + { + tweenToColor(printerConfig.stage9Color); // Customisable - Default is OFF printLogs("Stage 9, SCANNING BED SURFACE", printerConfig.stage9Color); return; } - //Inspecting First Layer - if (printerVariables.stage == 10 || printerVariables.overridestage == 10){ - tweenToColor(printerConfig.stage10Color); //Customisable - Default is OFF + // Inspecting First Layer + if (printerVariables.stage == 10 || printerVariables.overridestage == 10) + { + tweenToColor(printerConfig.stage10Color); // Customisable - Default is OFF printLogs("Stage 10 / HMS 0C00, FIRST LAYER INSPECTION", printerConfig.stage10Color); return; } - //Calibrating MicroLidar - if (printerVariables.stage == 12){ - tweenToColor(printerConfig.stage10Color); + // Calibrating MicroLidar + if (printerVariables.stage == 12) + { + tweenToColor(printerConfig.stage10Color); printLogs("Stage 12, CALIBRATING MICRO LIDAR", printerConfig.stage10Color); return; } // Idle Timeout (Has to be enabled) - if ((printerVariables.stage == -1 || printerVariables.stage == 255) - && !((printerConfig.finishExit && printerVariables.waitingForDoor) || (printerConfig.finishExit == false && ((millis() - printerConfig.finishStartms) < printerConfig.finishTimeOut))) - && (millis() - printerConfig.inactivityStartms) > printerConfig.inactivityTimeOut - && printerConfig.isIdleOFFActive == false - && printerConfig.inactivityEnabled){ - tweenToColor(0,0,0,0,0); //OFF + if ((printerVariables.stage == -1 || printerVariables.stage == 255) && !((printerConfig.finishExit && printerVariables.waitingForDoor) || (printerConfig.finishExit == false && ((millis() - printerConfig.finishStartms) < printerConfig.finishTimeOut))) && (millis() - printerConfig.inactivityStartms) > printerConfig.inactivityTimeOut && printerConfig.isIdleOFFActive == false && printerConfig.inactivityEnabled) + { + tweenToColor(0, 0, 0, 0, 0); // OFF printerConfig.isIdleOFFActive = true; - if (printerConfig.debuging || printerConfig.debugingchange){ - Serial.print(F("Idle Timeout [")); - Serial.print((int)(printerConfig.inactivityTimeOut / 60000)); - Serial.println(F(" mins] - Turning LEDs OFF")); + if (printerConfig.debuging || printerConfig.debugingchange) + { + LogSerial.print(F("Idle Timeout [")); + LogSerial.print((int)(printerConfig.inactivityTimeOut / 60000)); + LogSerial.println(F(" mins] - Turning LEDs OFF")); }; return; } - //ON -- ON -- ON -- ON + // ON -- ON -- ON -- ON - //Preheating Bed - if (printerVariables.stage == 2){ - tweenToColor(printerConfig.runningColor); //Customisable - Default is WHITE + // Preheating Bed + if (printerVariables.stage == 2) + { + tweenToColor(printerConfig.runningColor); // Customisable - Default is WHITE printLogs("Stage 2, PREHEATING BED", printerConfig.runningColor); return; } - //Printing or Resume after Pausing - if (printerVariables.stage == 0 && printerVariables.gcodeState == "RUNNING"){ - tweenToColor(printerConfig.runningColor); //Customisable - Default is WHITE + // Printing or Resume after Pausing + if (printerVariables.stage == 0 && printerVariables.gcodeState == "RUNNING") + { + tweenToColor(printerConfig.runningColor); // Customisable - Default is WHITE printLogs("Stage 0, PRINTING - gcodeState RUNNING", printerConfig.runningColor); return; } - //for IDLE - P1 uses 255, X1 uses -1 - if ((printerVariables.stage == -1 || printerVariables.stage == 255) - && !((printerConfig.finishExit && printerVariables.waitingForDoor) || (printerConfig.finishExit == false && ((millis() - printerConfig.finishStartms) < printerConfig.finishTimeOut))) - && (millis() - printerConfig.inactivityStartms < printerConfig.inactivityTimeOut)){ - tweenToColor(printerConfig.runningColor); //Customisable - Default is WHITE + // for IDLE - P1 uses 255, X1 uses -1 + if ((printerVariables.stage == -1 || printerVariables.stage == 255) && !((printerConfig.finishExit && printerVariables.waitingForDoor) || (printerConfig.finishExit == false && ((millis() - printerConfig.finishStartms) < printerConfig.finishTimeOut))) && (millis() - printerConfig.inactivityStartms < printerConfig.inactivityTimeOut)) + { + tweenToColor(printerConfig.runningColor); // Customisable - Default is WHITE printLogs("Stage -1/255, IDLE", printerConfig.runningColor); return; } - //User Cancelled Print - if (printerVariables.gcodeState == "FAILED"){ - tweenToColor(printerConfig.runningColor); //Customisable - Default is WHITE + // User Cancelled Print + if (printerVariables.gcodeState == "FAILED") + { + tweenToColor(printerConfig.runningColor); // Customisable - Default is WHITE printLogs("Stage -1/255, FAILED", printerConfig.runningColor); return; } - //Print file just sent - if (printerVariables.gcodeState == "PREPARE"){ - tweenToColor(printerConfig.runningColor); //Customisable - Default is WHITE + // Print file just sent + if (printerVariables.gcodeState == "PREPARE") + { + tweenToColor(printerConfig.runningColor); // Customisable - Default is WHITE printLogs("Stage -1/255, PREPARE", printerConfig.runningColor); return; } - //Homing ToolHead - if (printerVariables.stage == 13){ - //No color change assigned - Serial.println(F("STAGE 13, HOMING TOOL HEAD")); + // Homing ToolHead + if (printerVariables.stage == 13) + { + // No color change assigned + LogSerial.println(F("STAGE 13, HOMING TOOL HEAD")); return; } - //Offline - if (printerVariables.gcodeState == "OFFLINE" || printerVariables.stage == -2){ - tweenToColor(printerConfig.runningColor); //Customisable - Default is WHITE + // Offline + if (printerVariables.gcodeState == "OFFLINE" || printerVariables.stage == -2) + { + tweenToColor(printerConfig.runningColor); // Customisable - Default is WHITE printLogs("Stage -1/255, OFFLINE", printerConfig.runningColor); return; } - //GREEN -- GREEN -- GREEN -- GREEN + // GREEN -- GREEN -- GREEN -- GREEN - //Sets to green when print finishes AND user wants Finish Indication enabled - if (printerVariables.finished == true && printerConfig.finishindication == true){ - tweenToColor(printerConfig.finishColor); //Customisable - Default is GREEN + // Sets to green when print finishes AND user wants Finish Indication enabled + if (printerVariables.finished == true && printerConfig.finishindication == true) + { + tweenToColor(printerConfig.finishColor); // Customisable - Default is GREEN printLogs("Finished print", printerConfig.finishColor); printerVariables.finished = false; return; } // replicate printer behaviour ON - if (printerConfig.replicatestate && printerConfig.replicate_update && printerVariables.printerledstate - && !((printerConfig.finishExit && printerVariables.waitingForDoor) || (printerConfig.finishExit == false && ((millis() - printerConfig.finishStartms) < printerConfig.finishTimeOut)))){ - tweenToColor(printerConfig.runningColor); //Customisable - Default is WHITE + if (printerConfig.replicatestate && printerConfig.replicate_update && printerVariables.printerledstate && !((printerConfig.finishExit && printerVariables.waitingForDoor) || (printerConfig.finishExit == false && ((millis() - printerConfig.finishStartms) < printerConfig.finishTimeOut)))) + { + tweenToColor(printerConfig.runningColor); // Customisable - Default is WHITE printLogs("LED Replication ON", printerConfig.runningColor); printerConfig.replicate_update = false; return; } } - -void setupLeds() { - Serial.println(F("Updating from setupleds")); - pinMode(redPin, OUTPUT); - pinMode(greenPin, OUTPUT); - pinMode(bluePin, OUTPUT); - pinMode(coldPin, OUTPUT); - pinMode(warmPin, OUTPUT); +void setupLeds() +{ + LogSerial.println(F("Updating from setupleds")); + + ledcSetup(redChannel, pwmFreq, pwmResolution); + ledcSetup(greenChannel, pwmFreq, pwmResolution); + ledcSetup(blueChannel, pwmFreq, pwmResolution); + ledcSetup(warmChannel, pwmFreq, pwmResolution); + ledcSetup(coldChannel, pwmFreq, pwmResolution); + + ledcAttachPin(redPin, redChannel); + ledcAttachPin(greenPin, greenChannel); + ledcAttachPin(bluePin, blueChannel); + ledcAttachPin(warmPin, warmChannel); + ledcAttachPin(coldPin, coldChannel); } -void ledsloop(){ +void ledsloop() +{ RGBCycle(); - if((millis() - lastUpdatems) > 30000 && (printerConfig.maintMode || printerConfig.testcolorEnabled || printerConfig.discoMode || printerConfig.debugwifi)) { - Serial.print(F("[")); - Serial.print(millis()); - Serial.print(F("]")); - if(printerConfig.maintMode) Serial.println(F(" Maintenance Mode - next update in 30 seconds")); - if(printerConfig.testcolorEnabled) Serial.println(F(" Test Color - next update in 30 seconds")); - if(printerConfig.discoMode) Serial.println(F(" RGB Cycle Mode - next update in 30 seconds")); - if(printerConfig.debugwifi) Serial.println(F(" Wifi Debug Mode - next update in 30 seconds")); + if ((millis() - lastUpdatems) > 30000 && (printerConfig.maintMode || printerConfig.testcolorEnabled || printerConfig.discoMode || printerConfig.debugwifi)) + { + LogSerial.print(F("[")); + LogSerial.print(millis()); + LogSerial.print(F("]")); + if (printerConfig.maintMode) + LogSerial.println(F(" Maintenance Mode - next update in 30 seconds")); + if (printerConfig.testcolorEnabled) + LogSerial.println(F(" Test Color - next update in 30 seconds")); + if (printerConfig.discoMode) + LogSerial.println(F(" RGB Cycle Mode - next update in 30 seconds")); + if (printerConfig.debugwifi) + LogSerial.println(F(" Wifi Debug Mode - next update in 30 seconds")); lastUpdatems = millis(); } // Turn off GREEN if... finished and Door OPENED or CLOSED in last 5 secs AND user wants Finish Indication enabled // Can't use Boolean finished as printer defaults back to IDLE via MQTT - if((printerVariables.waitingForDoor && printerConfig.finishindication && printerConfig.finishExit - && ((millis() - printerVariables.lastdoorClosems) < 6000 || (millis() - printerVariables.lastdoorOpenms) < 6000))){ - if (printerConfig.debuging || printerConfig.debugingchange){ - Serial.println(F("Updating from finishloop after Door interaction - Starting IDLE timer")); + if ((printerVariables.waitingForDoor && printerConfig.finishindication && printerConfig.finishExit && ((millis() - printerVariables.lastdoorClosems) < 6000 || (millis() - printerVariables.lastdoorOpenms) < 6000))) + { + if (printerConfig.debuging || printerConfig.debugingchange) + { + LogSerial.println(F("Updating from finishloop after Door interaction - Starting IDLE timer")); } printerVariables.waitingForDoor = false; printerConfig.inactivityStartms = millis(); @@ -561,10 +645,11 @@ void ledsloop(){ updateleds(); } - if((printerConfig.finish_check && printerConfig.finishindication && printerConfig.finishExit == false - && ((millis() - printerConfig.finishStartms) > printerConfig.finishTimeOut))){ - if (printerConfig.debuging || printerConfig.debugingchange){ - Serial.println(F("Updating from finishloop after Finish timer expired - Starting IDLE timer")); + if ((printerConfig.finish_check && printerConfig.finishindication && printerConfig.finishExit == false && ((millis() - printerConfig.finishStartms) > printerConfig.finishTimeOut))) + { + if (printerConfig.debuging || printerConfig.debugingchange) + { + LogSerial.println(F("Updating from finishloop after Finish timer expired - Starting IDLE timer")); } printerConfig.finish_check = false; printerConfig.inactivityStartms = millis(); @@ -572,13 +657,11 @@ void ledsloop(){ updateleds(); } - //Need an trigger action to run updateleds() so lights turn off - //There is no change in the printer STATE, just monitoring the timer and triggering when over a threshhold - if(printerConfig.inactivityEnabled - && (millis() - printerConfig.inactivityStartms) > printerConfig.inactivityTimeOut - && printerVariables.finished == false && printerConfig.isIdleOFFActive == false) + // Need an trigger action to run updateleds() so lights turn off + // There is no change in the printer STATE, just monitoring the timer and triggering when over a threshhold + if (printerConfig.inactivityEnabled && (millis() - printerConfig.inactivityStartms) > printerConfig.inactivityTimeOut && printerVariables.finished == false && printerConfig.isIdleOFFActive == false) { - //Opening or Closing the Door will turn LEDs back on and restart the timer. + // Opening or Closing the Door will turn LEDs back on and restart the timer. updateleds(); } diff --git a/src/blled/logSerial.h b/src/blled/logSerial.h new file mode 100644 index 0000000..1ebb08c --- /dev/null +++ b/src/blled/logSerial.h @@ -0,0 +1,60 @@ +#ifndef LOGSERIAL_H +#define LOGSERIAL_H + +#include +#include + +class AsyncWebServer; + +class LogSerialClass : public Stream { +private: +WebSerial webSerial; +public: + void begin(unsigned long baud = 115200) { + Serial.begin(baud); + } + + void begin(AsyncWebServer* server, unsigned long baud = 115200, size_t bufferSize = 100) { + Serial.begin(baud); + webSerial.begin(server); + webSerial.setBuffer(bufferSize); + webSerial.onMessage([](const std::string& msg) { + Serial.print("[WebSerial RX] "); + Serial.println(msg.c_str()); + }); + } + + void onMessage(std::function cb) { + webSerial.onMessage(cb); + } + + void setBuffer(size_t size) { + webSerial.setBuffer(size); + } + + int available() override { return Serial.available(); } + int read() override { return Serial.read(); } + int peek() override { return Serial.peek(); } + void flush() override { Serial.flush(); } + + size_t write(uint8_t b) override { + Serial.write(b); + webSerial.write(&b, 1); + return 1; + } + + size_t write(const uint8_t* buffer, size_t size) override { + Serial.write(buffer, size); + webSerial.write(buffer, size); + return size; + } + + using Print::write; + operator bool() { return (bool)Serial; } + + +}; + +LogSerialClass LogSerial; + +#endif // LOGSERIAL_H diff --git a/src/blled/message.json b/src/blled/message.json deleted file mode 100644 index d07b706..0000000 --- a/src/blled/message.json +++ /dev/null @@ -1,588 +0,0 @@ -{ - "print": { - "3D": { - "layer_num": 0, - "total_layer_num": 0 - }, - "ams": { - "ams": [ - { - "dry_time": 0, - "humidity": "5", - "humidity_raw": "20", - "id": "0", - "info": "1001", - "temp": "22.2", - "tray": [ - { - "bed_temp": "0", - "bed_temp_type": "0", - "cali_idx": 2740, - "cols": [ - "161616FF" - ], - "ctype": 0, - "drying_temp": "0", - "drying_time": "0", - "id": "0", - "nozzle_temp_max": "240", - "nozzle_temp_min": "190", - "remain": -1, - "state": 11, - "tag_uid": "0000000000000000", - "total_len": 330000, - "tray_color": "161616FF", - "tray_diameter": "1.75", - "tray_id_name": "", - "tray_info_idx": "GFL99", - "tray_sub_brands": "", - "tray_type": "PLA", - "tray_uuid": "00000000000000000000000000000000", - "tray_weight": "0", - "xcam_info": "000000000000000000000000" - }, - { - "bed_temp": "0", - "bed_temp_type": "0", - "cali_idx": -1, - "cols": [ - "F98C36FF" - ], - "ctype": 0, - "drying_temp": "0", - "drying_time": "0", - "id": "1", - "nozzle_temp_max": "240", - "nozzle_temp_min": "190", - "remain": -1, - "state": 11, - "tag_uid": "0000000000000000", - "total_len": 330000, - "tray_color": "F98C36FF", - "tray_diameter": "1.75", - "tray_id_name": "", - "tray_info_idx": "GFL99", - "tray_sub_brands": "", - "tray_type": "PLA", - "tray_uuid": "00000000000000000000000000000000", - "tray_weight": "0", - "xcam_info": "000000000000000000000000" - }, - { - "bed_temp": "35", - "bed_temp_type": "1", - "cali_idx": 3693, - "cols": [ - "792B36FF" - ], - "ctype": 0, - "drying_temp": "55", - "drying_time": "8", - "id": "2", - "nozzle_temp_max": "230", - "nozzle_temp_min": "190", - "remain": 40, - "state": 11, - "tag_uid": "A0E4C32F00000100", - "total_len": 330000, - "tray_color": "792B36FF", - "tray_diameter": "1.75", - "tray_id_name": "A08-R2", - "tray_info_idx": "GFA08", - "tray_sub_brands": "PLA Sparkle", - "tray_type": "PLA", - "tray_uuid": "D481BCAAC6E043C8BEA355364A1CF641", - "tray_weight": "1000", - "xcam_info": "1027EC2CBC02E8033333333F" - }, - { - "bed_temp": "0", - "bed_temp_type": "0", - "cali_idx": 208, - "cols": [ - "F98C36FF" - ], - "ctype": 0, - "drying_temp": "0", - "drying_time": "0", - "id": "3", - "nozzle_temp_max": "240", - "nozzle_temp_min": "190", - "remain": -1, - "state": 11, - "tag_uid": "0000000000000000", - "total_len": 330000, - "tray_color": "F98C36FF", - "tray_diameter": "1.75", - "tray_id_name": "", - "tray_info_idx": "GFL99", - "tray_sub_brands": "", - "tray_type": "PLA", - "tray_uuid": "00000000000000000000000000000000", - "tray_weight": "0", - "xcam_info": "000000000000000000000000" - } - ] - }, - { - "dry_time": 0, - "humidity": "5", - "humidity_raw": "18", - "id": "1", - "info": "2003", - "temp": "19.9", - "tray": [ - { - "bed_temp": "0", - "bed_temp_type": "0", - "cali_idx": -1, - "cols": [ - "FFFFFFFF" - ], - "ctype": 0, - "drying_temp": "65", - "drying_time": "8", - "id": "0", - "nozzle_temp_max": "260", - "nozzle_temp_min": "230", - "remain": 27, - "state": 11, - "tag_uid": "BA919CF000000100", - "total_len": 330000, - "tray_color": "FFFFFFFF", - "tray_diameter": "1.75", - "tray_id_name": "G02-W0", - "tray_info_idx": "GFG02", - "tray_sub_brands": "PETG HF", - "tray_type": "PETG", - "tray_uuid": "2B5A1171556548DDA48A14D87FC0C041", - "tray_weight": "1000", - "xcam_info": "803E803E8403E8030000803F" - }, - { - "bed_temp": "0", - "bed_temp_type": "0", - "cali_idx": -1, - "cols": [ - "87909AFF" - ], - "ctype": 0, - "drying_temp": "0", - "drying_time": "0", - "id": "1", - "nozzle_temp_max": "270", - "nozzle_temp_min": "220", - "remain": -1, - "state": 11, - "tag_uid": "0000000000000000", - "total_len": 330000, - "tray_color": "87909AFF", - "tray_diameter": "1.75", - "tray_id_name": "", - "tray_info_idx": "GFG99", - "tray_sub_brands": "", - "tray_type": "PETG", - "tray_uuid": "00000000000000000000000000000000", - "tray_weight": "0", - "xcam_info": "000000000000000000000000" - }, - { - "bed_temp": "0", - "bed_temp_type": "0", - "cali_idx": -1, - "cols": [ - "FFFFFFFF" - ], - "ctype": 0, - "drying_temp": "0", - "drying_time": "0", - "id": "2", - "nozzle_temp_max": "280", - "nozzle_temp_min": "240", - "remain": -1, - "state": 11, - "tag_uid": "0000000000000000", - "total_len": 330000, - "tray_color": "FFFFFFFF", - "tray_diameter": "1.75", - "tray_id_name": "", - "tray_info_idx": "GFB99", - "tray_sub_brands": "", - "tray_type": "ABS", - "tray_uuid": "00000000000000000000000000000000", - "tray_weight": "0", - "xcam_info": "000000000000000000000000" - }, - { - "bed_temp": "80", - "bed_temp_type": "1", - "cali_idx": -1, - "cols": [ - "87909AFF" - ], - "ctype": 0, - "drying_temp": "80", - "drying_time": "8", - "id": "3", - "nozzle_temp_max": "270", - "nozzle_temp_min": "240", - "remain": 96, - "state": 11, - "tag_uid": "205F1AFF00000100", - "total_len": 330000, - "tray_color": "87909AFF", - "tray_diameter": "1.75", - "tray_id_name": "B00-D1", - "tray_info_idx": "GFB00", - "tray_sub_brands": "ABS", - "tray_type": "ABS", - "tray_uuid": "F7B057CBC44348C4B92A1971036811E1", - "tray_weight": "1000", - "xcam_info": "D007D007E803E8036666663F" - } - ] - } - ], - "ams_exist_bits": "3", - "ams_exist_bits_raw": "3", - "cali_id": 0, - "cali_stat": 0, - "insert_flag": false, - "power_on_flag": false, - "tray_exist_bits": "ff", - "tray_is_bbl_bits": "ff", - "tray_now": "255", - "tray_pre": "255", - "tray_read_done_bits": "ff", - "tray_reading_bits": "0", - "tray_tar": "255", - "unbind_ams_stat": 0, - "version": 863 - }, - "ams_rfid_status": 0, - "ams_status": 0, - "ap_err": 0, - "aux": "280100C", - "aux_part_fan": true, - "batch_id": 0, - "bed_target_temper": 0, - "bed_temper": 19, - "big_fan1_speed": "0", - "big_fan2_speed": "0", - "cali_version": 0, - "canvas_id": 0, - "care": [ - { - "id": "cr", - "info": "20631064" - }, - { - "id": "ls", - "info": "67F984D" - } - ], - "cfg": "FCA98", - "command": "push_status", - "cooling_fan_speed": "0", - "design_id": "", - "device": { - "bed": { - "info": { - "temp": 19 - }, - "state": 0 - }, - "bed_temp": 19, - "cam": { - "laser": { - "cond": 253, - "state": 0 - } - }, - "ctc": { - "info": { - "temp": 21 - }, - "state": 0 - }, - "ext_tool": { - "calib": 2, - "low_prec": true, - "mount": 0, - "th_temp": 0, - "type": "" - }, - "extruder": { - "info": [ - { - "filam_bak": [ - 10 - ], - "hnow": 0, - "hpre": 0, - "htar": 0, - "id": 0, - "info": 8, - "snow": 65535, - "spre": 65535, - "star": 65535, - "stat": 0, - "temp": 20 - } - ], - "state": 1 - }, - "fan": 0, - "laser": { - "power": 0 - }, - "nozzle": { - "exist": 1, - "info": [ - { - "diameter": 0.4, - "id": 0, - "tm": 0, - "type": "HX01", - "wear": 0 - } - ], - "state": 0 - }, - "plate": { - "base": 1, - "cali2d_id": "", - "cur_id": "", - "mat": 1, - "tar_id": "" - }, - "type": 1 - }, - "err": "0", - "fail_reason": "0", - "fan_gear": 0, - "file": "", - "force_upgrade": false, - "fun": "11A30F9CFF", - "gcode_file": "", - "gcode_file_prepare_percent": "0", - "gcode_state": "IDLE", - "heatbreak_fan_speed": "0", - "hms": [], - - - "home_flag": -1067070056, #tΓΌr zu bin -111111100110100011001001101000 - "home_flag": -1058681448, #tΓΌr auf bin -111111000110100011001001101000 - - -1 ---------------------------------------- --1058681448 offen -1 ---------------------------------------- --1067070056 zu -1 - - - "hw_switch_state": 0, - "info": { - "temp": 21 - }, - "ipcam": { - "agora_service": "disable", - "brtc_service": "enable", - "bs_state": 0, - "ipcam_dev": "1", - "ipcam_record": "enable", - "laser_preview_res": 7, - "mode_bits": 2, - "resolution": "1080p", - "rtsp_url": "disable", - "timelapse": "disable", - "tl_store_hpd_type": 2, - "tl_store_path_type": 2, - "tutk_server": "disable" - }, - "job": { - "cur_stage": { - "idx": 0, - "state": 0 - }, - "stage": [] - }, - "job_attr": 3, - "job_id": "", - "layer_num": 0, - "lights_report": [ - { - "mode": "on", - "node": "chamber_light" - }, - { - "mode": "flashing", - "node": "work_light" - } - ], - "mapping": [], - "mc_action": 0, - "mc_err": 0, - "mc_percent": 0, - "mc_print_error_code": "0", - "mc_print_stage": "1", - "mc_print_sub_stage": 0, - "mc_remaining_time": 0, - "mc_stage": 1, - "model_id": "", - "net": { - "conf": 16, - "info": [ - { - "ip": 2317877770, - "mask": 16777215 - }, - { - "ip": 0, - "mask": 0 - } - ] - }, - "nozzle_diameter": "0.4", - "nozzle_target_temper": 0, - "nozzle_temper": 20, - "nozzle_type": "hardened_steel", - "online": { - "ahb": true, - "ext": false, - "version": 6 - }, - "percent": 0, - "plate_cnt": 0, - "plate_id": 0, - "plate_idx": 0, - "prepare_per": 0, - "print_error": 0, - "print_gcode_action": 0, - "print_real_action": 0, - "print_type": "", - "profile_id": "", - "project_id": "", - "queue": 0, - "queue_est": 0, - "queue_number": 0, - "queue_sts": 0, - "queue_total": 0, - "remain_time": 0, - "s_obj": [], - "sdcard": true, - "sequence_id": "2021", - "spd_lvl": 2, - "spd_mag": 100, - "stat": "7A48000", - "state": 0, - "stg": [], - "stg_cur": -1, - "subtask_id": "", - "subtask_name": "", - "task_id": "", - "total_layer_num": 0, - "upgrade_state": { - "ahb_new_version_number": "", - "ams_new_version_number": "", - "consistency_request": false, - "dis_state": 0, - "err_code": 0, - "ext_new_version_number": "", - "force_upgrade": false, - "idx": 6, - "idx2": 745459320, - "lower_limit": "00.00.00.00", - "message": "", - "module": "", - "new_version_state": 2, - "ota_new_version_number": "", - "progress": "0", - "sequence_id": 0, - "sn": "00M09B431900386", - "status": "IDLE" - }, - "upload": { - "file_size": 0, - "finish_size": 0, - "message": "Good", - "oss_url": "", - "progress": 0, - "sequence_id": "0903", - "speed": 0, - "status": "idle", - "task_id": "", - "time_remaining": 0, - "trouble_id": "" - }, - "ver": "20010", - "vir_slot": [ - { - "bed_temp": "0", - "bed_temp_type": "0", - "cali_idx": -1, - "cols": [ - "BCBCBCFF" - ], - "ctype": 0, - "drying_temp": "0", - "drying_time": "0", - "id": "255", - "nozzle_temp_max": "250", - "nozzle_temp_min": "200", - "remain": 0, - "tag_uid": "0000000000000000", - "total_len": 330000, - "tray_color": "BCBCBCFF", - "tray_diameter": "1.75", - "tray_id_name": "", - "tray_info_idx": "GFU99", - "tray_sub_brands": "", - "tray_type": "TPU", - "tray_uuid": "00000000000000000000000000000000", - "tray_weight": "0", - "xcam_info": "000000000000000000000000" - } - ], - "vt_tray": { - "bed_temp": "0", - "bed_temp_type": "0", - "cali_idx": -1, - "cols": [ - "BCBCBCFF" - ], - "ctype": 0, - "drying_temp": "0", - "drying_time": "0", - "id": "255", - "nozzle_temp_max": "250", - "nozzle_temp_min": "200", - "remain": 0, - "tag_uid": "0000000000000000", - "total_len": 330000, - "tray_color": "BCBCBCFF", - "tray_diameter": "1.75", - "tray_id_name": "", - "tray_info_idx": "GFU99", - "tray_sub_brands": "", - "tray_type": "TPU", - "tray_uuid": "00000000000000000000000000000000", - "tray_weight": "0", - "xcam_info": "000000000000000000000000" - }, - "wifi_signal": "-33dBm", - "xcam": { - "allow_skip_parts": false, - "buildplate_marker_detector": true, - "first_layer_inspector": false, - "halt_print_sensitivity": "medium", - "print_halt": true, - "printing_monitor": true, - "spaghetti_detector": true - }, - "xcam_status": "0" - } -} \ No newline at end of file diff --git a/src/blled/mqttmanager.h b/src/blled/mqttmanager.h index 95258b8..52659d2 100644 --- a/src/blled/mqttmanager.h +++ b/src/blled/mqttmanager.h @@ -24,6 +24,9 @@ AutoGrowBufferStream stream; unsigned long mqttattempt = (millis() - 3000); unsigned long lastMQTTupdate = millis(); +TaskHandle_t mqttTaskHandle = NULL; +bool mqttTaskRunning = false; + // With a Default BLLED // Expected information when viewing MQTT status messages @@ -43,43 +46,43 @@ unsigned long lastMQTTupdate = millis(); void connectMqtt() { - if (WiFi.status() != WL_CONNECTED) + if (WiFi.status() != WL_CONNECTED || WiFi.getMode() != WIFI_MODE_STA) { // Abort MQTT connection attempt when no Wifi return; } if (strlen(printerConfig.printerIP) == 0 || strlen(printerConfig.accessCode) == 0) { - Serial.println(F("[MQTT] Abort connect: printerIP oder accessCode wrong or empty")); + LogSerial.println(F("[MQTT] Abort connect: printerIP oder accessCode wrong or empty")); return; } if (!mqttClient.connected() && (millis() - mqttattempt) >= 3000) { tweenToColor(10, 10, 10, 10, 10); - Serial.println(F("Connecting to mqtt...")); + LogSerial.println(F("Connecting to mqtt...")); if (mqttClient.connect(clientId.c_str(), "bblp", printerConfig.accessCode)) { - Serial.print(F("MQTT connected, subscribing to MQTT Topic: ")); - Serial.println(report_topic); + LogSerial.print(F("MQTT connected, subscribing to MQTT Topic: ")); + LogSerial.println(report_topic); mqttClient.subscribe(report_topic.c_str()); printerVariables.online = true; printerVariables.disconnectMQTTms = 0; - // Serial.println(F("Updating LEDs from MQTT connect")); + // LogSerial.println(F("Updating LEDs from MQTT connect")); // updateleds(); } else { - Serial.println(F("Failed to connect with error code: ")); - Serial.print(mqttClient.state()); - Serial.print(F(" ")); + LogSerial.println(F("Failed to connect with error code: ")); + LogSerial.print(mqttClient.state()); + LogSerial.print(F(" ")); ParseMQTTState(mqttClient.state()); if (mqttClient.state() == 5) { - delay(500); + //delay(500); tweenToColor(127, 0, 0, 0, 0); // light red, indicating not authorized - delay(500); + //delay(500); mqttattempt = (millis() - 3000); - // Serial.println(F("Restarting Device")); + // LogSerial.println(F("Restarting Device")); // delay(1000); // ESP.restart(); } @@ -87,6 +90,46 @@ void connectMqtt() } } +void mqttTask(void *parameter) +{ + mqttTaskRunning = true; + + while (true) + { + if (WiFi.status() != WL_CONNECTED || WiFi.getMode() != WIFI_MODE_STA) + { + printerVariables.online = false; + vTaskDelay(pdMS_TO_TICKS(2000)); + continue; + } + + if (!mqttClient.connected()) + { + printerVariables.online = false; + + if (printerVariables.disconnectMQTTms == 0) + { + printerVariables.disconnectMQTTms = millis(); + LogSerial.println(F("[MQTT Task] Disconnected")); + ParseMQTTState(mqttClient.state()); + } + + connectMqtt(); + vTaskDelay(pdMS_TO_TICKS(32)); + } + else + { + printerVariables.disconnectMQTTms = 0; + mqttClient.loop(); + } + + vTaskDelay(pdMS_TO_TICKS(10)); + } + + mqttTaskRunning = false; + vTaskDelete(NULL); +} + void ParseCallback(char *topic, byte *payload, unsigned int length) { JsonDocument messageobject; @@ -112,14 +155,14 @@ void ParseCallback(char *topic, byte *payload, unsigned int length) { if (printerConfig.debuging) { - Serial.println(F("Mqtt message received.")); - Serial.print(F("FreeHeap: ")); - Serial.println(ESP.getFreeHeap()); + LogSerial.println(F("Mqtt message received.")); + LogSerial.print(F("FreeHeap: ")); + LogSerial.println(ESP.getFreeHeap()); } bool Changed = false; - if (messageobject["print"]["command"].is()) + if (!messageobject["print"]["command"].isNull()) { if (messageobject["print"]["command"] == "gcode_line" // gcode_line used a lot during print initialisations - Skip these || messageobject["print"]["command"] == "project_prepare" // 1 message per print @@ -127,7 +170,8 @@ void ParseCallback(char *topic, byte *payload, unsigned int length) || messageobject["print"]["command"] == "clean_print_error" // During error (no info) || messageobject["print"]["command"] == "resume" // After error or pause || messageobject["print"]["command"] == "get_accessories" // After error or pause - || messageobject["print"]["command"] == "prepare") + || messageobject["print"]["command"] == "prepare" + || messageobject["print"]["command"] == "extrusion_cali_get") { // 1 message per print return; } @@ -141,30 +185,30 @@ void ParseCallback(char *topic, byte *payload, unsigned int length) // Output Filtered MQTT message if (printerConfig.mqttdebug) { - Serial.print(F("(Filtered) MQTT payload, [")); - Serial.print(millis()); - Serial.print(F("], ")); - serializeJson(messageobject, Serial); - Serial.println(); + LogSerial.print(F("(Filtered) MQTT payload, [")); + LogSerial.print(millis()); + LogSerial.print(F("], ")); + serializeJson(messageobject, LogSerial); + LogSerial.println(); } if (printerConfig.mqttdebug && (printerConfig.maintMode || printerConfig.testcolorEnabled || printerConfig.discoMode || printerConfig.debugwifi)) { - Serial.print(F("MQTT Message Ignored while in ")); + LogSerial.print(F("MQTT Message Ignored while in ")); if (printerConfig.maintMode) - Serial.print(F("Maintenance")); + LogSerial.print(F("Maintenance")); if (printerConfig.testcolorEnabled) - Serial.print(F("Test Color")); + LogSerial.print(F("Test Color")); if (printerConfig.discoMode) - Serial.print(F("RGB Cycle")); + LogSerial.print(F("RGB Cycle")); if (printerConfig.debugwifi) - Serial.print(F("Wifi Debug")); - Serial.println(F(" mode")); + LogSerial.print(F("Wifi Debug")); + LogSerial.println(F(" mode")); return; } // Check for Door Status - if (messageobject["print"]["home_flag"].is()) + if (!messageobject["print"]["home_flag"].isNull()) { // https://github.com/greghesp/ha-bambulab/blob/main/custom_components/bambu_lab/pybambu/const.py#L324 @@ -178,12 +222,12 @@ void ParseCallback(char *topic, byte *payload, unsigned int length) printerVariables.doorOpen = doorState; if (printerConfig.debugingchange) - Serial.print(F("MQTT Door ")); + LogSerial.print(F("MQTT Door ")); if (printerVariables.doorOpen) { printerVariables.lastdoorOpenms = millis(); if (printerConfig.debugingchange) - Serial.println(F("Opened")); + LogSerial.println(F("Opened")); } else { @@ -193,14 +237,14 @@ void ParseCallback(char *topic, byte *payload, unsigned int length) } printerVariables.lastdoorClosems = millis(); if (printerConfig.debugingchange) - Serial.println(F("Closed")); + LogSerial.println(F("Closed")); } Changed = true; } } // Check BBLP Stage - if (messageobject["print"]["stg_cur"].is()) + if (!messageobject["print"]["stg_cur"].isNull()) { if (printerVariables.stage != messageobject["print"]["stg_cur"].as()) { @@ -208,15 +252,15 @@ void ParseCallback(char *topic, byte *payload, unsigned int length) if (printerConfig.debugingchange || printerConfig.debuging) { - Serial.print(F("MQTT update - stg_cur now: ")); - Serial.println(printerVariables.stage); + LogSerial.print(F("MQTT update - stg_cur now: ")); + LogSerial.println(printerVariables.stage); } Changed = true; } } // Check BBLP GCode State - if (messageobject["print"]["gcode_state"].is() && ((millis() - lastMQTTupdate) > 3000)) + if (!messageobject["print"]["gcode_state"].isNull() && ((millis() - lastMQTTupdate) > 3000)) { String mqttgcodeState = messageobject["print"]["gcode_state"].as(); @@ -240,27 +284,27 @@ void ParseCallback(char *topic, byte *payload, unsigned int length) if (printerConfig.debugingchange || printerConfig.debuging) { - Serial.print(F("MQTT update - gcode_state now: ")); - Serial.println(printerVariables.gcodeState); + LogSerial.print(F("MQTT update - gcode_state now: ")); + LogSerial.println(printerVariables.gcodeState); } Changed = true; } } // Pause Command - quicker, but Only for user generated pause - error & code pauses don't trigger this. - if (messageobject["print"]["command"].is()) + if (!messageobject["print"]["command"].isNull()) { if (messageobject["print"]["command"] == "pause") { lastMQTTupdate = millis(); - Serial.println(F("MQTT update - manual PAUSE")); + LogSerial.println(F("MQTT update - manual PAUSE")); printerVariables.gcodeState = "PAUSE"; Changed = true; } } // Added a delay so the slower MQTT status message doesn't reverse the "system" commands - if (messageobject["print"]["lights_report"].is() && ((millis() - lastMQTTupdate) > 3000)) + if (!messageobject["print"]["lights_report"].isNull() && ((millis() - lastMQTTupdate) > 3000)) { JsonArray lightsReport = messageobject["print"]["lights_report"]; for (JsonObject light : lightsReport) @@ -274,8 +318,8 @@ void ParseCallback(char *topic, byte *payload, unsigned int length) printerConfig.replicate_update = true; if (printerConfig.debugingchange || printerConfig.debuging) { - Serial.print(F("MQTT chamber_light now: ")); - Serial.println(printerVariables.printerledstate); + LogSerial.print(F("MQTT chamber_light now: ")); + LogSerial.println(printerVariables.printerledstate); } if (printerVariables.waitingForDoor && printerConfig.finish_check) { @@ -288,7 +332,7 @@ void ParseCallback(char *topic, byte *payload, unsigned int length) } // System Commands are sent quicker than the push_status // Message only sent onChange - if (messageobject["system"]["command"].is()) + if (!messageobject["system"]["command"].isNull()) { if (messageobject["system"]["command"] == "ledctrl") { @@ -300,8 +344,8 @@ void ParseCallback(char *topic, byte *payload, unsigned int length) lastMQTTupdate = millis(); if (printerConfig.debugingchange || printerConfig.debuging) { - Serial.print(F("MQTT led_mode now: ")); - Serial.println(printerVariables.printerledstate); + LogSerial.print(F("MQTT led_mode now: ")); + LogSerial.println(printerVariables.printerledstate); } if (printerVariables.waitingForDoor && printerConfig.finish_check) { @@ -314,7 +358,7 @@ void ParseCallback(char *topic, byte *payload, unsigned int length) } // Bambu Health Management System (HMS) - if (messageobject["print"]["hms"].is()) + if (!messageobject["print"]["hms"].isNull()) { String oldHMSlevel = ""; oldHMSlevel = printerVariables.parsedHMSlevel; @@ -346,31 +390,31 @@ void ParseCallback(char *topic, byte *payload, unsigned int length) if (printerConfig.debuging || printerConfig.debugingchange) { - Serial.print(F("MQTT update - parsedHMSlevel now: ")); + LogSerial.print(F("MQTT update - parsedHMSlevel now: ")); if (printerVariables.parsedHMSlevel.length() > 0) { - Serial.print(printerVariables.parsedHMSlevel); - Serial.print(F(" Error Code: ")); - // Serial.println(F("https://wiki.bambulab.com/en/x1/troubleshooting/how-to-enter-the-specific-code-page")); + LogSerial.print(printerVariables.parsedHMSlevel); + LogSerial.print(F(" Error Code: ")); + // LogSerial.println(F("https://wiki.bambulab.com/en/x1/troubleshooting/how-to-enter-the-specific-code-page")); int chunk1 = (printerVariables.parsedHMScode >> 48); int chunk2 = (printerVariables.parsedHMScode >> 32) & 0xFFFF; int chunk3 = (printerVariables.parsedHMScode >> 16) & 0xFFFF; int chunk4 = printerVariables.parsedHMScode & 0xFFFF; char strHMScode[20]; sprintf(strHMScode, "%04X_%04X_%04X_%04X", chunk1, chunk2, chunk3, chunk4); - Serial.print(strHMScode); + LogSerial.print(strHMScode); if (printerVariables.overridestage != printerVariables.stage) { - Serial.println(F(" **")); + LogSerial.println(F(" **")); } else { - Serial.println(F("")); + LogSerial.println(F("")); } } else { - Serial.println(F("NULL")); + LogSerial.println(F("NULL")); printerVariables.overridestage = 999; } } @@ -384,7 +428,7 @@ void ParseCallback(char *topic, byte *payload, unsigned int length) printerConfig.isIdleOFFActive = false; if (printerConfig.debuging) { - Serial.println(F("Change from mqtt")); + LogSerial.println(F("Change from mqtt")); } printerConfig.maintMode_update = true; printerConfig.discoMode_update = true; @@ -396,7 +440,7 @@ void ParseCallback(char *topic, byte *payload, unsigned int length) } else { - Serial.println(F("Deserialize error while parsing mqtt")); + LogSerial.println(F("Deserialize error while parsing mqtt")); return; } } @@ -410,25 +454,62 @@ void mqttCallback(char *topic, byte *payload, unsigned int length) void setupMqtt() { clientId += String(random(0xffff), HEX); - Serial.print(F("Setting up MQTT with Bambu Lab Printer IP address: ")); - Serial.println(printerConfig.printerIP); + LogSerial.print(F("Setting up MQTT with Bambu Lab Printer IP address: ")); + LogSerial.println(printerConfig.printerIP); device_topic = String("device/") + printerConfig.serialNumber; report_topic = device_topic + String("/report"); wifiSecureClient.setInsecure(); - mqttClient.setBufferSize(1024); // 1024 + wifiSecureClient.setTimeout(3); + mqttClient.setSocketTimeout(3); + mqttClient.setBufferSize(1024); mqttClient.setServer(printerConfig.printerIP, 8883); mqttClient.setStream(stream); mqttClient.setCallback(mqttCallback); - mqttClient.setSocketTimeout(20); - Serial.println(F("Finished setting up MQTT")); - connectMqtt(); + + LogSerial.println(F("Finished setting up MQTT")); + + if (mqttTaskHandle == NULL) + { + BaseType_t result; + + #if CONFIG_FREERTOS_UNICORE + result = xTaskCreate( + mqttTask, + "mqttTask", + 6144, + NULL, + 1, + &mqttTaskHandle + ); + #else + result = xTaskCreatePinnedToCore( + mqttTask, + "mqttTask", + 6144, + NULL, + 1, + &mqttTaskHandle, + 1 // Core 1 (App Core) + ); + #endif + + if (result == pdPASS) + { + LogSerial.println(F("MQTT task successfully started")); + } + else + { + LogSerial.println(F("Failed to create MQTT task!")); + } + } } + void mqttloop() { - if (WiFi.status() != WL_CONNECTED) + if (WiFi.status() != WL_CONNECTED || WiFi.getMode() != WIFI_MODE_STA) { // Abort MQTT connection attempt when no Wifi return; @@ -441,10 +522,10 @@ void mqttloop() { printerVariables.disconnectMQTTms = millis(); // Record last time MQTT dropped connection - Serial.println(F("MQTT dropped during mqttloop")); + LogSerial.println(F("MQTT dropped during mqttloop")); ParseMQTTState(mqttClient.state()); } - delay(500); + //delay(500); connectMqtt(); delay(32); return; diff --git a/src/blled/mqttparsingutility.h b/src/blled/mqttparsingutility.h index 1040314..ebc7d05 100644 --- a/src/blled/mqttparsingutility.h +++ b/src/blled/mqttparsingutility.h @@ -23,34 +23,34 @@ void ParseMQTTState(int code){ switch (code) { case -4: // MQTT_CONNECTION_TIMEOUT - Serial.println(F("MQTT TIMEOUT")); + LogSerial.println(F("MQTT TIMEOUT")); break; case -3: // MQTT_CONNECTION_LOST - Serial.println(F("MQTT CONNECTION_LOST")); + LogSerial.println(F("MQTT CONNECTION_LOST")); break; case -2: // MQTT_CONNECT_FAILED - Serial.println(F("MQTT CONNECT_FAILED")); + LogSerial.println(F("MQTT CONNECT_FAILED")); break; case -1: // MQTT_DISCONNECTED - Serial.println(F("MQTT DISCONNECTED")); + LogSerial.println(F("MQTT DISCONNECTED")); break; case 0: // MQTT_CONNECTED - Serial.println(F("MQTT CONNECTED")); + LogSerial.println(F("MQTT CONNECTED")); break; case 1: // MQTT_CONNECT_BAD_PROTOCOL - Serial.println(F("MQTT BAD PROTOCOL")); + LogSerial.println(F("MQTT BAD PROTOCOL")); break; case 2: // MQTT_CONNECT_BAD_CLIENT_ID - Serial.println(F("MQTT BAD CLIENT ID")); + LogSerial.println(F("MQTT BAD CLIENT ID")); break; case 3: // MQTT_CONNECT_UNAVAILABLE - Serial.println(F("MQTT UNAVAILABLE")); + LogSerial.println(F("MQTT UNAVAILABLE")); break; case 4: // MQTT_CONNECT_BAD_CREDENTIALS - Serial.println(F("MQTT BAD CREDENTIALS")); + LogSerial.println(F("MQTT BAD CREDENTIALS")); break; case 5: // MQTT UNAUTHORIZED - Serial.println(F("MQTT UNAUTHORIZED")); + LogSerial.println(F("MQTT UNAUTHORIZED")); break; } } diff --git a/src/blled/types.h b/src/blled/types.h index 4e05e76..ec4bd72 100644 --- a/src/blled/types.h +++ b/src/blled/types.h @@ -54,7 +54,7 @@ extern "C" typedef struct GlobalVariablesStruct{ char SSID[32]; - char APPW[32]; + char APPW[64]; String FWVersion = STRVERSION; String Host = "BLLED"; bool started = false; diff --git a/src/blled/web-server.h b/src/blled/web-server.h index 5affcab..df0c61c 100644 --- a/src/blled/web-server.h +++ b/src/blled/web-server.h @@ -14,8 +14,6 @@ AsyncWebServer webServer(80); AsyncWebSocket ws("/ws"); #include "../www/www.h" -#include "../www/blled_svg.h" -#include "../www/favicon.h" unsigned long lastWsPush = 0; const unsigned long wsPushInterval = 1000; // alle 1000ms @@ -207,6 +205,17 @@ void handlePrinterConfigJson(AsyncWebServerRequest *request) request->send(200, "application/json", json); } +void handleStyleCss(AsyncWebServerRequest *request) +{ + if (!isAuthorized(request)) + { + return request->requestAuthentication(); + } + AsyncWebServerResponse *response = request->beginResponse(200, style_css_gz_mime, style_css_gz, style_css_gz_len); + response->addHeader("Content-Encoding", "gzip"); + request->send(response); +} + void handleSubmitConfig(AsyncWebServerRequest *request) { if (!isAuthorized(request)) @@ -214,83 +223,56 @@ void handleSubmitConfig(AsyncWebServerRequest *request) return request->requestAuthentication(); } - bool newBSSID = false; - printerConfig.brightness = request->getParam("brightnessslider", true)->value().toInt(); - printerConfig.rescanWiFiNetwork = (request->hasParam("rescanWiFiNetwork", true)); - printerConfig.maintMode = (request->hasParam("maintMode", true)); - printerConfig.discoMode = (request->hasParam("discoMode", true)); - printerConfig.replicatestate = (request->hasParam("replicateLedState", true)); - printerConfig.runningColor = hex2rgb(request->getParam("runningRGB", true)->value().c_str(), - request->getParam("runningWW", true)->value().toInt(), - request->getParam("runningCW", true)->value().toInt()); - printerConfig.testcolorEnabled = (request->hasParam("showtestcolor", true)); - printerConfig.testColor = hex2rgb(request->getParam("testRGB", true)->value().c_str(), - request->getParam("testWW", true)->value().toInt(), - request->getParam("testCW", true)->value().toInt()); - printerConfig.debugwifi = (request->hasParam("debugwifi", true)); - printerConfig.finishindication = (request->hasParam("finishIndication", true)); - printerConfig.finishColor = hex2rgb(request->getParam("finishColor", true)->value().c_str(), - request->getParam("finishWW", true)->value().toInt(), - request->getParam("finishCW", true)->value().toInt()); - printerConfig.finishExit = !(request->hasParam("finishEndTimer", true)); - printerConfig.finishTimeOut = request->getParam("finishTimerMins", true)->value().toInt() * 60000; - printerConfig.inactivityEnabled = (request->hasParam("inactivityEnabled", true)); - printerConfig.inactivityTimeOut = request->getParam("inactivityMins", true)->value().toInt() * 60000; - printerConfig.debuging = (request->hasParam("debuging", true)); - printerConfig.debugingchange = (request->hasParam("debugingchange", true)); - printerConfig.mqttdebug = (request->hasParam("mqttdebug", true)); - printerVariables.isP1Printer = (request->hasParam("p1Printer", true)); - printerVariables.useDoorSwtich = (request->hasParam("doorSwitch", true)); - - printerConfig.stage14Color = hex2rgb(request->getParam("stage14RGB", true)->value().c_str(), - request->getParam("stage14WW", true)->value().toInt(), - request->getParam("stage14CW", true)->value().toInt()); - printerConfig.stage1Color = hex2rgb(request->getParam("stage1RGB", true)->value().c_str(), - request->getParam("stage1WW", true)->value().toInt(), - request->getParam("stage1CW", true)->value().toInt()); - printerConfig.stage8Color = hex2rgb(request->getParam("stage8RGB", true)->value().c_str(), - request->getParam("stage8WW", true)->value().toInt(), - request->getParam("stage8CW", true)->value().toInt()); - printerConfig.stage9Color = hex2rgb(request->getParam("stage9RGB", true)->value().c_str(), - request->getParam("stage9WW", true)->value().toInt(), - request->getParam("stage9CW", true)->value().toInt()); - printerConfig.stage10Color = hex2rgb(request->getParam("stage10RGB", true)->value().c_str(), - request->getParam("stage10WW", true)->value().toInt(), - request->getParam("stage10CW", true)->value().toInt()); - printerConfig.errordetection = (request->hasParam("errorDetection", true)); - printerConfig.wifiRGB = hex2rgb(request->getParam("wifiRGB", true)->value().c_str(), - request->getParam("wifiWW", true)->value().toInt(), - request->getParam("wifiCW", true)->value().toInt()); - printerConfig.pauseRGB = hex2rgb(request->getParam("pauseRGB", true)->value().c_str(), - request->getParam("pauseWW", true)->value().toInt(), - request->getParam("pauseCW", true)->value().toInt()); - printerConfig.firstlayerRGB = hex2rgb(request->getParam("firstlayerRGB", true)->value().c_str(), - request->getParam("firstlayerWW", true)->value().toInt(), - request->getParam("firstlayerCW", true)->value().toInt()); - printerConfig.nozzleclogRGB = hex2rgb(request->getParam("nozzleclogRGB", true)->value().c_str(), - request->getParam("nozzleclogWW", true)->value().toInt(), - request->getParam("nozzleclogCW", true)->value().toInt()); - printerConfig.hmsSeriousRGB = hex2rgb(request->getParam("hmsSeriousRGB", true)->value().c_str(), - request->getParam("hmsSeriousWW", true)->value().toInt(), - request->getParam("hmsSeriousCW", true)->value().toInt()); - printerConfig.hmsFatalRGB = hex2rgb(request->getParam("hmsFatalRGB", true)->value().c_str(), - request->getParam("hmsFatalWW", true)->value().toInt(), - request->getParam("hmsFatalCW", true)->value().toInt()); - printerConfig.filamentRunoutRGB = hex2rgb(request->getParam("filamentRunoutRGB", true)->value().c_str(), - request->getParam("filamentRunoutWW", true)->value().toInt(), - request->getParam("filamentRunoutCW", true)->value().toInt()); - printerConfig.frontCoverRGB = hex2rgb(request->getParam("frontCoverRGB", true)->value().c_str(), - request->getParam("frontCoverWW", true)->value().toInt(), - request->getParam("frontCoverCW", true)->value().toInt()); - printerConfig.nozzleTempRGB = hex2rgb(request->getParam("nozzleTempRGB", true)->value().c_str(), - request->getParam("nozzleTempWW", true)->value().toInt(), - request->getParam("nozzleTempCW", true)->value().toInt()); - printerConfig.bedTempRGB = hex2rgb(request->getParam("bedTempRGB", true)->value().c_str(), - request->getParam("bedTempWW", true)->value().toInt(), - request->getParam("bedTempCW", true)->value().toInt()); + auto getSafeParamValue = [](AsyncWebServerRequest *req, const char *name, const char *fallback = "") -> String + { + return req->hasParam(name, true) ? req->getParam(name, true)->value() : fallback; + }; + + auto getSafeParamInt = [](AsyncWebServerRequest *req, const char *name, int fallback = 0) -> int + { + return req->hasParam(name, true) ? req->getParam(name, true)->value().toInt() : fallback; + }; + + printerConfig.brightness = getSafeParamInt(request, "brightnessslider"); + printerConfig.rescanWiFiNetwork = request->hasParam("rescanWiFiNetwork", true); + printerConfig.maintMode = request->hasParam("maintMode", true); + printerConfig.discoMode = request->hasParam("discoMode", true); + printerConfig.replicatestate = request->hasParam("replicateLedState", true); + printerConfig.runningColor = hex2rgb(getSafeParamValue(request, "runningRGB").c_str(), getSafeParamInt(request, "runningWW"), getSafeParamInt(request, "runningCW")); + printerConfig.testcolorEnabled = request->hasParam("showtestcolor", true); + printerConfig.testColor = hex2rgb(getSafeParamValue(request, "testRGB").c_str(), getSafeParamInt(request, "testWW"), getSafeParamInt(request, "testCW")); + printerConfig.debugwifi = request->hasParam("debugwifi", true); + printerConfig.finishindication = request->hasParam("finishIndication", true); + printerConfig.finishColor = hex2rgb(getSafeParamValue(request, "finishColor").c_str(), getSafeParamInt(request, "finishWW"), getSafeParamInt(request, "finishCW")); + printerConfig.finishExit = !request->hasParam("finishEndTimer", true); + printerConfig.finishTimeOut = getSafeParamInt(request, "finishTimerMins") * 60000; + printerConfig.inactivityEnabled = request->hasParam("inactivityEnabled", true); + printerConfig.inactivityTimeOut = getSafeParamInt(request, "inactivityMins") * 60000; + printerConfig.debuging = request->hasParam("debuging", true); + printerConfig.debugingchange = request->hasParam("debugingchange", true); + printerConfig.mqttdebug = request->hasParam("mqttdebug", true); + printerVariables.isP1Printer = request->hasParam("p1Printer", true); + printerVariables.useDoorSwtich = request->hasParam("doorSwitch", true); + + printerConfig.stage14Color = hex2rgb(getSafeParamValue(request, "stage14RGB").c_str(), getSafeParamInt(request, "stage14WW"), getSafeParamInt(request, "stage14CW")); + printerConfig.stage1Color = hex2rgb(getSafeParamValue(request, "stage1RGB").c_str(), getSafeParamInt(request, "stage1WW"), getSafeParamInt(request, "stage1CW")); + printerConfig.stage8Color = hex2rgb(getSafeParamValue(request, "stage8RGB").c_str(), getSafeParamInt(request, "stage8WW"), getSafeParamInt(request, "stage8CW")); + printerConfig.stage9Color = hex2rgb(getSafeParamValue(request, "stage9RGB").c_str(), getSafeParamInt(request, "stage9WW"), getSafeParamInt(request, "stage9CW")); + printerConfig.stage10Color = hex2rgb(getSafeParamValue(request, "stage10RGB").c_str(), getSafeParamInt(request, "stage10WW"), getSafeParamInt(request, "stage10CW")); + printerConfig.errordetection = request->hasParam("errorDetection", true); + printerConfig.wifiRGB = hex2rgb(getSafeParamValue(request, "wifiRGB").c_str(), getSafeParamInt(request, "wifiWW"), getSafeParamInt(request, "wifiCW")); + printerConfig.pauseRGB = hex2rgb(getSafeParamValue(request, "pauseRGB").c_str(), getSafeParamInt(request, "pauseWW"), getSafeParamInt(request, "pauseCW")); + printerConfig.firstlayerRGB = hex2rgb(getSafeParamValue(request, "firstlayerRGB").c_str(), getSafeParamInt(request, "firstlayerWW"), getSafeParamInt(request, "firstlayerCW")); + printerConfig.nozzleclogRGB = hex2rgb(getSafeParamValue(request, "nozzleclogRGB").c_str(), getSafeParamInt(request, "nozzleclogWW"), getSafeParamInt(request, "nozzleclogCW")); + printerConfig.hmsSeriousRGB = hex2rgb(getSafeParamValue(request, "hmsSeriousRGB").c_str(), getSafeParamInt(request, "hmsSeriousWW"), getSafeParamInt(request, "hmsSeriousCW")); + printerConfig.hmsFatalRGB = hex2rgb(getSafeParamValue(request, "hmsFatalRGB").c_str(), getSafeParamInt(request, "hmsFatalWW"), getSafeParamInt(request, "hmsFatalCW")); + printerConfig.filamentRunoutRGB = hex2rgb(getSafeParamValue(request, "filamentRunoutRGB").c_str(), getSafeParamInt(request, "filamentRunoutWW"), getSafeParamInt(request, "filamentRunoutCW")); + printerConfig.frontCoverRGB = hex2rgb(getSafeParamValue(request, "frontCoverRGB").c_str(), getSafeParamInt(request, "frontCoverWW"), getSafeParamInt(request, "frontCoverCW")); + printerConfig.nozzleTempRGB = hex2rgb(getSafeParamValue(request, "nozzleTempRGB").c_str(), getSafeParamInt(request, "nozzleTempWW"), getSafeParamInt(request, "nozzleTempCW")); + printerConfig.bedTempRGB = hex2rgb(getSafeParamValue(request, "bedTempRGB").c_str(), getSafeParamInt(request, "bedTempWW"), getSafeParamInt(request, "bedTempCW")); saveFileSystem(); - Serial.println(F("Packet received from setuppage")); + LogSerial.println(F("Packet received from setuppage")); printerConfig.inactivityStartms = millis(); printerConfig.isIdleOFFActive = false; printerConfig.replicate_update = true; @@ -298,7 +280,7 @@ void handleSubmitConfig(AsyncWebServerRequest *request) printerConfig.discoMode_update = true; printerConfig.testcolor_update = true; updateleds(); - request->redirect("/"); + request->send(200, "text/plain", "OK"); } void sendJsonToAll(JsonDocument &doc) @@ -349,23 +331,23 @@ void handleSubmitWiFi(AsyncWebServerRequest *request) if (ssid.length() > 0 && pass.length() > 0) { - Serial.println(F("[WiFiSetup] Updating WiFi credentials:")); - Serial.print(F("SSID: ")); - Serial.println(ssid); - Serial.print(F("Password: ")); - Serial.println(pass); + LogSerial.println(F("[WiFiSetup] Updating WiFi credentials:")); + LogSerial.print(F("SSID: ")); + LogSerial.println(ssid); + LogSerial.print(F("Password: ")); + LogSerial.println(pass); strlcpy(globalVariables.SSID, ssid.c_str(), sizeof(globalVariables.SSID)); strlcpy(globalVariables.APPW, pass.c_str(), sizeof(globalVariables.APPW)); } else { - Serial.println(F("[WiFiSetup] Empty SSID or PASS received β†’ ignoring WiFi update.")); + LogSerial.println(F("[WiFiSetup] Empty SSID or PASS received β†’ ignoring WiFi update.")); } } else { - Serial.println(F("[WiFiSetup] No SSID or PASS provided β†’ keeping existing WiFi credentials.")); + LogSerial.println(F("[WiFiSetup] No SSID or PASS provided β†’ keeping existing WiFi credentials.")); } // Optional other fields (printerIP, printerSerial, etc.) @@ -407,10 +389,8 @@ void websocketLoop() doc["doorOpen"] = printerVariables.doorOpen; doc["printerConnection"] = printerVariables.online; doc["clients"] = ws.count(); - + doc["stg_cur"] = printerVariables.stage; sendJsonToAll(doc); - - Serial.println(F("[WS] JSON Status Push send.")); } } @@ -429,14 +409,49 @@ void handleDownloadConfigFile(AsyncWebServerRequest *request) { return request->requestAuthentication(); } + if (!LittleFS.exists(configPath)) { request->send(404, "text/plain", "Config file not found"); return; } - request->send(LittleFS, configPath, "application/json", true, nullptr); + + File configFile = LittleFS.open(configPath, "r"); + if (!configFile) + { + request->send(500, "text/plain", "Failed to open config file"); + return; + } + + JsonDocument doc; + DeserializationError error = deserializeJson(doc, configFile); + configFile.close(); + + if (error) + { + request->send(500, "text/plain", "Failed to parse config file"); + return; + } + + String jsonString; + serializeJsonPretty(doc, jsonString); + + AsyncWebServerResponse *response = request->beginResponse(200, "application/json", jsonString); + response->addHeader("Content-Disposition", "attachment; filename=\"blledconfig.json\""); + request->send(response); +} + + +void handleWebSerialPage(AsyncWebServerRequest *request) +{ + if (!isAuthorized(request)) + return request->requestAuthentication(); + AsyncWebServerResponse *response = request->beginResponse(200, webSerialPage_html_gz_mime, webSerialPage_html_gz, webSerialPage_html_gz_len); + response->addHeader("Content-Encoding", "gzip"); + request->send(response); } + void handleUploadConfigFileData(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final) { @@ -444,7 +459,7 @@ void handleUploadConfigFileData(AsyncWebServerRequest *request, const String &fi if (!index) { - Serial.println(F("[ConfigUpload] Start")); + LogSerial.println(F("[ConfigUpload] Start")); uploadFile = LittleFS.open(configPath, "w"); } if (uploadFile) @@ -454,7 +469,7 @@ void handleUploadConfigFileData(AsyncWebServerRequest *request, const String &fi if (final) { uploadFile.close(); - Serial.println(F("[ConfigUpload] Finished")); + LogSerial.println(F("[ConfigUpload] Finished")); } shouldRestart = true; restartRequestTime = millis(); @@ -466,20 +481,21 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp switch (type) { case WS_EVT_CONNECT: - Serial.printf("[WS] Client connected: %u\n", client->id()); + LogSerial.printf("[WS] Client connected: %u\n", client->id()); + websocketLoop(); break; case WS_EVT_DISCONNECT: - Serial.printf("[WS] Client disconnected: %u\n", client->id()); + LogSerial.printf("[WS] Client disconnected: %u\n", client->id()); ws.cleanupClients(); break; case WS_EVT_DATA: - Serial.printf("[WS] Data received from client %u\n", client->id()); + LogSerial.printf("[WS] Data received from client %u\n", client->id()); break; case WS_EVT_PONG: - Serial.printf("[WS] Pong received from %u\n", client->id()); + LogSerial.printf("[WS] Pong received from %u\n", client->id()); break; case WS_EVT_ERROR: - Serial.printf("[WS] Error on connection %u\n", client->id()); + LogSerial.printf("[WS] Error on connection %u\n", client->id()); ws.cleanupClients(); break; } @@ -489,38 +505,38 @@ void setupWebserver() { if (!MDNS.begin(globalVariables.Host.c_str())) { - Serial.println(F("Error setting up MDNS responder!")); + LogSerial.println(F("Error setting up MDNS responder!")); while (1) delay(500); } - Serial.println(F("Setting up webserver")); + LogSerial.println(F("Setting up webserver")); webServer.on("/", HTTP_GET, [](AsyncWebServerRequest *request) { if (WiFi.getMode() == WIFI_AP) { - Serial.println(F("[WebServer] Captive Portal activ – redirect to /wifi")); + LogSerial.println(F("[WebServer] Captive Portal activ – redirect to /wifi")); request->redirect("/wifi"); } else { + handleSetup(request); //handleOldSetup(request); - handleOldSetup(request); } }); - // webServer.on("/old", HTTP_GET, handleOldSetup); - webServer.on("/old", HTTP_GET, handleSetup); + webServer.on("/old", HTTP_GET, handleOldSetup); webServer.on("/fwupdate", HTTP_GET, handleUpdatePage); webServer.on("/getConfig", HTTP_GET, handleGetConfig); webServer.on("/submitConfig", HTTP_POST, handleSubmitConfig); - webServer.on("/blled.png", HTTP_GET, handleGetIcon); + webServer.on("/blled.svg", HTTP_GET, handleGetIcon); webServer.on("/favicon.ico", HTTP_GET, handleGetfavicon); webServer.on("/particleCanvas.js", HTTP_GET, handleGetPCC); webServer.on("/config.json", HTTP_GET, handlePrinterConfigJson); webServer.on("/wifi", HTTP_GET, handleWiFiSetupPage); webServer.on("/wifiScan", HTTP_GET, handleWiFiScan); webServer.on("/submitWiFi", HTTP_POST, handleSubmitWiFi); - + webServer.on("/style.css", HTTP_GET, handleStyleCss); webServer.on("/backuprestore", HTTP_GET, handleConfigPage); webServer.on("/configfile.json", HTTP_GET, handleDownloadConfigFile); - webServer.on("/confirestore", HTTP_POST, [](AsyncWebServerRequest *request) + webServer.on("/webserial", HTTP_GET, handleWebSerialPage); + webServer.on("/configrestore", HTTP_POST, [](AsyncWebServerRequest *request) { if (!isAuthorized(request)) { return request->requestAuthentication(); @@ -532,7 +548,7 @@ void setupWebserver() static File uploadFile; if (!index) { - Serial.printf("[ConfigUpload] Start: %s\n", filename.c_str()); + LogSerial.printf("[ConfigUpload] Start: %s\n", filename.c_str()); uploadFile = LittleFS.open(configPath, "w"); } if (uploadFile) { @@ -540,40 +556,43 @@ void setupWebserver() } if (final) { uploadFile.close(); - Serial.println(F("[ConfigUpload] Finished")); + LogSerial.println(F("[ConfigUpload] Finished")); } }); webServer.on("/update", HTTP_POST, [](AsyncWebServerRequest *request) { request->send(200, "text/plain", "OK"); - Serial.println(F("Restarting Device")); + LogSerial.println(F("OTA Upload done. Marking for restart.")); shouldRestart = true; - restartRequestTime = millis(); }); - - webServer.onFileUpload([](AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final) - { + restartRequestTime = millis(); }, [](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) + { if (!index) { - Serial.printf("Update: %s\n", filename.c_str()); + LogSerial.printf("[OTA] Start: %s\n", filename.c_str()); if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { - Update.printError(Serial); + Update.printError(LogSerial); } } + if (Update.write(data, len) != len) { - Update.printError(Serial); + Update.printError(LogSerial); } + if (final) { if (Update.end(true)) { - Serial.printf("Update Success: %u\nRebooting...\n", index + len); + LogSerial.printf("[OTA] Success (%u bytes). Awaiting reboot...\n", index + len); } else { - Update.printError(Serial); + Update.printError(LogSerial); } } }); + LogSerial.begin(&webServer); + ws.onEvent(onWsEvent); webServer.addHandler(&ws); + webServer.begin(); - Serial.println(F("Webserver started")); + LogSerial.println(F("Webserver started")); } #endif diff --git a/src/main.cpp b/src/main.cpp index 50cf6ae..4ccd435 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,7 @@ #include bool shouldRestart = false; unsigned long restartRequestTime = 0; +#include "./blled/logSerial.h" #include "./blled/web-server.h" #include "./blled/mqttmanager.h" #include "./blled/filesystem.h" @@ -14,7 +15,7 @@ int wifi_reconnect_count = 0; void defaultcolors() { - Serial.println(F("Setting default customisable colors")); + LogSerial.println(F("Setting default customisable colors")); printerConfig.runningColor = hex2rgb("#000000", 255, 255); // WHITE Running printerConfig.testColor = hex2rgb("#3F3CFB"); // Violet Test printerConfig.finishColor = hex2rgb("#00FF00"); // Green Finish @@ -70,19 +71,21 @@ void setup() setupWebserver(); return; } + else - if (!connectToWifi()) + if (!connectToWifi()) { Serial.println(F("[WiFiManager] Not connected β†’ AP Mode")); startAPMode(); setupWebserver(); return; } - Serial.println(F("[WiFiManager] connected. Starting webUI.")); - setupWebserver(); - - tweenToColor(0, 0, 255, 0, 0); // BLUE - setupWebserver(); + else + { + Serial.println(F("[WiFiManager] connected. Starting webUI.")); + tweenToColor(0, 0, 255, 0, 0); // BLUE + setupWebserver(); + } start_ssdp(); @@ -105,16 +108,15 @@ void loop() serialLoop(); if (globalVariables.started) { - mqttloop(); websocketLoop(); ledsloop(); if (WiFi.status() != WL_CONNECTED) { - Serial.print(F("Wifi connection dropped. ")); - Serial.print(F("Wifi Status: ")); - Serial.println(wl_status_to_string(WiFi.status())); - Serial.println(F("Attempting to reconnect to WiFi...")); + LogSerial.print(F("Wifi connection dropped. ")); + LogSerial.print(F("Wifi Status: ")); + LogSerial.println(wl_status_to_string(WiFi.status())); + LogSerial.println(F("Attempting to reconnect to WiFi...")); wifi_reconnect_count += 1; if (wifi_reconnect_count <= 2) { @@ -138,7 +140,7 @@ void loop() } if (printerConfig.rescanWiFiNetwork) { - Serial.println(F("Web submitted refresh of Wifi Scan (assigning Strongest AP)")); + LogSerial.println(F("Web submitted refresh of Wifi Scan (assigning Strongest AP)")); tweenToColor(printerConfig.wifiRGB); // Customisable - Default is ORANGE scanNetwork(); // Sets the MAC address for following connection attempt printerConfig.rescanWiFiNetwork = false; @@ -146,7 +148,7 @@ void loop() } if (shouldRestart && millis() - restartRequestTime > 1500) { - Serial.println(F("[WiFiSetup] Restarting now...")); + LogSerial.println(F("[WiFiSetup] Restarting now...")); ESP.restart(); } } \ No newline at end of file diff --git a/src/www/backupRestore.html b/src/www/backupRestore.html index 2e9cb8a..c4bd36c 100644 --- a/src/www/backupRestore.html +++ b/src/www/backupRestore.html @@ -5,103 +5,35 @@ BLLED Config Backup - +
-

Download current config:

- - +
+ +

+
+ +

+ diff --git a/src/www/blled_svg.h b/src/www/blled_svg.h deleted file mode 100644 index 9fc8a0d..0000000 --- a/src/www/blled_svg.h +++ /dev/null @@ -1,232 +0,0 @@ -#include -//https://tomeko.net/online_tools/file_to_hex.php?lang=en -const unsigned int BBLED_svg_len = 3626; -const uint8_t BBLED_svg[] PROGMEM = { -0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, -0x2E, 0x30, 0x22, 0x20, 0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22, 0x55, 0x54, -0x46, 0x2D, 0x38, 0x22, 0x20, 0x73, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x6C, 0x6F, 0x6E, 0x65, 0x3D, -0x22, 0x6E, 0x6F, 0x22, 0x3F, 0x3E, 0x0A, 0x3C, 0x21, 0x2D, 0x2D, 0x20, 0x43, 0x72, 0x65, 0x61, -0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x49, 0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, -0x65, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x69, 0x6E, -0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x29, 0x20, 0x2D, 0x2D, 0x3E, -0x0A, 0x0A, 0x3C, 0x73, 0x76, 0x67, 0x0A, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3D, -0x22, 0x37, 0x33, 0x2E, 0x35, 0x38, 0x33, 0x38, 0x34, 0x37, 0x6D, 0x6D, 0x22, 0x0A, 0x20, 0x20, -0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3D, 0x22, 0x31, 0x31, 0x38, 0x2E, 0x34, 0x35, 0x31, -0x36, 0x31, 0x6D, 0x6D, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42, 0x6F, 0x78, -0x3D, 0x22, 0x30, 0x20, 0x30, 0x20, 0x37, 0x33, 0x2E, 0x35, 0x38, 0x33, 0x38, 0x34, 0x38, 0x20, -0x31, 0x31, 0x38, 0x2E, 0x34, 0x35, 0x31, 0x36, 0x32, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x76, 0x65, -0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x31, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x69, -0x64, 0x3D, 0x22, 0x73, 0x76, 0x67, 0x31, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x78, 0x6D, 0x6C, 0x3A, -0x73, 0x70, 0x61, 0x63, 0x65, 0x3D, 0x22, 0x70, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x22, -0x0A, 0x20, 0x20, 0x20, 0x69, 0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x3A, 0x76, 0x65, 0x72, -0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x34, 0x20, 0x28, 0x38, 0x36, 0x61, 0x38, 0x61, -0x64, 0x37, 0x2C, 0x20, 0x32, 0x30, 0x32, 0x34, 0x2D, 0x31, 0x30, 0x2D, 0x31, 0x31, 0x29, 0x22, -0x0A, 0x20, 0x20, 0x20, 0x73, 0x6F, 0x64, 0x69, 0x70, 0x6F, 0x64, 0x69, 0x3A, 0x64, 0x6F, 0x63, -0x6E, 0x61, 0x6D, 0x65, 0x3D, 0x22, 0x62, 0x6C, 0x6C, 0x65, 0x64, 0x2E, 0x73, 0x76, 0x67, 0x22, -0x0A, 0x20, 0x20, 0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3A, 0x69, 0x6E, 0x6B, 0x73, 0x63, 0x61, -0x70, 0x65, 0x3D, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x69, -0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x6E, 0x61, 0x6D, 0x65, -0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2F, 0x69, 0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x22, -0x0A, 0x20, 0x20, 0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3A, 0x73, 0x6F, 0x64, 0x69, 0x70, 0x6F, -0x64, 0x69, 0x3D, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x73, 0x6F, 0x64, 0x69, 0x70, -0x6F, 0x64, 0x69, 0x2E, 0x73, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x66, 0x6F, 0x72, 0x67, 0x65, 0x2E, -0x6E, 0x65, 0x74, 0x2F, 0x44, 0x54, 0x44, 0x2F, 0x73, 0x6F, 0x64, 0x69, 0x70, 0x6F, 0x64, 0x69, -0x2D, 0x30, 0x2E, 0x64, 0x74, 0x64, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, -0x3D, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x33, 0x2E, -0x6F, 0x72, 0x67, 0x2F, 0x32, 0x30, 0x30, 0x30, 0x2F, 0x73, 0x76, 0x67, 0x22, 0x0A, 0x20, 0x20, -0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3A, 0x73, 0x76, 0x67, 0x3D, 0x22, 0x68, 0x74, 0x74, 0x70, -0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x33, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x32, 0x30, -0x30, 0x30, 0x2F, 0x73, 0x76, 0x67, 0x22, 0x3E, 0x3C, 0x73, 0x6F, 0x64, 0x69, 0x70, 0x6F, 0x64, -0x69, 0x3A, 0x6E, 0x61, 0x6D, 0x65, 0x64, 0x76, 0x69, 0x65, 0x77, 0x0A, 0x20, 0x20, 0x20, 0x20, -0x20, 0x69, 0x64, 0x3D, 0x22, 0x6E, 0x61, 0x6D, 0x65, 0x64, 0x76, 0x69, 0x65, 0x77, 0x31, 0x22, -0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x67, 0x65, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3D, -0x22, 0x23, 0x35, 0x30, 0x35, 0x30, 0x35, 0x30, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, -0x6F, 0x72, 0x64, 0x65, 0x72, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3D, 0x22, 0x23, 0x65, 0x65, 0x65, -0x65, 0x65, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, -0x6F, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3D, 0x22, 0x31, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, -0x20, 0x69, 0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x3A, 0x73, 0x68, 0x6F, 0x77, 0x70, 0x61, -0x67, 0x65, 0x73, 0x68, 0x61, 0x64, 0x6F, 0x77, 0x3D, 0x22, 0x30, 0x22, 0x0A, 0x20, 0x20, 0x20, -0x20, 0x20, 0x69, 0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x3A, 0x70, 0x61, 0x67, 0x65, 0x6F, -0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3D, 0x22, 0x30, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, -0x69, 0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x3A, 0x70, 0x61, 0x67, 0x65, 0x63, 0x68, 0x65, -0x63, 0x6B, 0x65, 0x72, 0x62, 0x6F, 0x61, 0x72, 0x64, 0x3D, 0x22, 0x30, 0x22, 0x0A, 0x20, 0x20, -0x20, 0x20, 0x20, 0x69, 0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x3A, 0x64, 0x65, 0x73, 0x6B, -0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3D, 0x22, 0x23, 0x35, 0x30, 0x35, 0x30, 0x35, 0x30, 0x22, 0x0A, -0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x3A, 0x64, 0x6F, -0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2D, 0x75, 0x6E, 0x69, 0x74, 0x73, 0x3D, 0x22, 0x6D, 0x6D, -0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x3A, -0x7A, 0x6F, 0x6F, 0x6D, 0x3D, 0x22, 0x30, 0x2E, 0x37, 0x31, 0x38, 0x39, 0x31, 0x38, 0x33, 0x35, -0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x3A, -0x63, 0x78, 0x3D, 0x22, 0x2D, 0x33, 0x31, 0x36, 0x2E, 0x34, 0x34, 0x37, 0x36, 0x32, 0x22, 0x0A, -0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x3A, 0x63, 0x79, -0x3D, 0x22, 0x32, 0x32, 0x36, 0x2E, 0x30, 0x33, 0x34, 0x30, 0x31, 0x22, 0x0A, 0x20, 0x20, 0x20, -0x20, 0x20, 0x69, 0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x3A, 0x77, 0x69, 0x6E, 0x64, 0x6F, -0x77, 0x2D, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3D, 0x22, 0x31, 0x39, 0x32, 0x30, 0x22, 0x0A, 0x20, -0x20, 0x20, 0x20, 0x20, 0x69, 0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x3A, 0x77, 0x69, 0x6E, -0x64, 0x6F, 0x77, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3D, 0x22, 0x31, 0x30, 0x30, 0x39, -0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x3A, -0x77, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x2D, 0x78, 0x3D, 0x22, 0x2D, 0x38, 0x22, 0x0A, 0x20, 0x20, -0x20, 0x20, 0x20, 0x69, 0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x3A, 0x77, 0x69, 0x6E, 0x64, -0x6F, 0x77, 0x2D, 0x79, 0x3D, 0x22, 0x2D, 0x38, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, -0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x3A, 0x77, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x2D, 0x6D, -0x61, 0x78, 0x69, 0x6D, 0x69, 0x7A, 0x65, 0x64, 0x3D, 0x22, 0x31, 0x22, 0x0A, 0x20, 0x20, 0x20, -0x20, 0x20, 0x69, 0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x3A, 0x63, 0x75, 0x72, 0x72, 0x65, -0x6E, 0x74, 0x2D, 0x6C, 0x61, 0x79, 0x65, 0x72, 0x3D, 0x22, 0x6C, 0x61, 0x79, 0x65, 0x72, 0x31, -0x22, 0x20, 0x2F, 0x3E, 0x3C, 0x64, 0x65, 0x66, 0x73, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, -0x64, 0x3D, 0x22, 0x64, 0x65, 0x66, 0x73, 0x31, 0x22, 0x20, 0x2F, 0x3E, 0x3C, 0x67, 0x0A, 0x20, -0x20, 0x20, 0x20, 0x20, 0x69, 0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x3A, 0x6C, 0x61, 0x62, -0x65, 0x6C, 0x3D, 0x22, 0x45, 0x62, 0x65, 0x6E, 0x65, 0x20, 0x31, 0x22, 0x0A, 0x20, 0x20, 0x20, -0x20, 0x20, 0x69, 0x6E, 0x6B, 0x73, 0x63, 0x61, 0x70, 0x65, 0x3A, 0x67, 0x72, 0x6F, 0x75, 0x70, -0x6D, 0x6F, 0x64, 0x65, 0x3D, 0x22, 0x6C, 0x61, 0x79, 0x65, 0x72, 0x22, 0x0A, 0x20, 0x20, 0x20, -0x20, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x6C, 0x61, 0x79, 0x65, 0x72, 0x31, 0x22, 0x0A, 0x20, 0x20, -0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x66, 0x6F, 0x72, 0x6D, 0x3D, 0x22, 0x74, 0x72, -0x61, 0x6E, 0x73, 0x6C, 0x61, 0x74, 0x65, 0x28, 0x2D, 0x31, 0x38, 0x38, 0x2E, 0x36, 0x34, 0x36, -0x36, 0x32, 0x2C, 0x2D, 0x38, 0x38, 0x2E, 0x35, 0x37, 0x32, 0x30, 0x30, 0x33, 0x29, 0x22, 0x3E, -0x3C, 0x70, 0x61, 0x74, 0x68, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x79, -0x6C, 0x65, 0x3D, 0x22, 0x66, 0x69, 0x6C, 0x6C, 0x3A, 0x23, 0x30, 0x31, 0x61, 0x37, 0x34, 0x66, -0x3B, 0x66, 0x69, 0x6C, 0x6C, 0x2D, 0x6F, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3A, 0x31, 0x22, -0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x3D, 0x22, 0x6D, 0x20, 0x32, 0x32, 0x32, -0x2E, 0x33, 0x38, 0x33, 0x33, 0x38, 0x2C, 0x32, 0x30, 0x36, 0x2E, 0x36, 0x39, 0x34, 0x35, 0x37, -0x20, 0x63, 0x20, 0x2D, 0x34, 0x2E, 0x31, 0x31, 0x38, 0x36, 0x36, 0x2C, 0x2D, 0x31, 0x2E, 0x31, -0x39, 0x32, 0x30, 0x31, 0x20, 0x2D, 0x37, 0x2E, 0x34, 0x38, 0x30, 0x37, 0x38, 0x2C, 0x2D, 0x33, -0x2E, 0x39, 0x33, 0x31, 0x31, 0x36, 0x20, 0x2D, 0x39, 0x2E, 0x31, 0x37, 0x30, 0x32, 0x32, 0x2C, -0x2D, 0x37, 0x2E, 0x34, 0x37, 0x31, 0x30, 0x36, 0x20, 0x2D, 0x30, 0x2E, 0x35, 0x38, 0x33, 0x31, -0x39, 0x2C, 0x2D, 0x31, 0x2E, 0x32, 0x32, 0x31, 0x39, 0x35, 0x20, 0x2D, 0x31, 0x2E, 0x30, 0x36, -0x30, 0x33, 0x34, 0x2C, 0x2D, 0x32, 0x2E, 0x34, 0x35, 0x39, 0x31, 0x38, 0x20, 0x2D, 0x31, 0x2E, -0x30, 0x36, 0x30, 0x33, 0x34, 0x2C, 0x2D, 0x32, 0x2E, 0x37, 0x34, 0x39, 0x33, 0x39, 0x20, 0x30, -0x2C, 0x2D, 0x30, 0x2E, 0x33, 0x32, 0x32, 0x39, 0x31, 0x20, 0x2D, 0x30, 0x2E, 0x34, 0x37, 0x35, -0x31, 0x39, 0x2C, 0x2D, 0x30, 0x2E, 0x36, 0x31, 0x36, 0x38, 0x31, 0x20, 0x2D, 0x31, 0x2E, 0x32, -0x32, 0x34, 0x35, 0x38, 0x2C, 0x2D, 0x30, 0x2E, 0x37, 0x35, 0x37, 0x34, 0x20, 0x2D, 0x32, 0x2E, -0x30, 0x33, 0x31, 0x36, 0x35, 0x2C, 0x2D, 0x30, 0x2E, 0x33, 0x38, 0x31, 0x31, 0x34, 0x20, 0x2D, -0x32, 0x2E, 0x33, 0x30, 0x33, 0x31, 0x39, 0x2C, 0x2D, 0x31, 0x2E, 0x31, 0x34, 0x32, 0x34, 0x32, -0x20, 0x2D, 0x32, 0x2E, 0x33, 0x30, 0x33, 0x31, 0x39, 0x2C, 0x2D, 0x36, 0x2E, 0x34, 0x35, 0x37, -0x30, 0x39, 0x20, 0x76, 0x20, 0x2D, 0x34, 0x2E, 0x36, 0x38, 0x37, 0x34, 0x33, 0x20, 0x6C, 0x20, -0x31, 0x36, 0x2E, 0x37, 0x39, 0x35, 0x30, 0x31, 0x2C, 0x30, 0x2E, 0x30, 0x39, 0x31, 0x36, 0x20, -0x31, 0x36, 0x2E, 0x37, 0x39, 0x35, 0x2C, 0x30, 0x2E, 0x30, 0x39, 0x31, 0x36, 0x20, 0x2D, 0x30, -0x2E, 0x30, 0x35, 0x35, 0x39, 0x2C, 0x34, 0x2E, 0x39, 0x32, 0x34, 0x31, 0x38, 0x20, 0x63, 0x20, -0x2D, 0x30, 0x2E, 0x30, 0x33, 0x32, 0x32, 0x2C, 0x32, 0x2E, 0x38, 0x33, 0x34, 0x32, 0x34, 0x20, -0x2D, 0x30, 0x2E, 0x32, 0x31, 0x33, 0x30, 0x37, 0x2C, 0x35, 0x2E, 0x31, 0x31, 0x33, 0x36, 0x32, -0x20, 0x2D, 0x30, 0x2E, 0x34, 0x32, 0x36, 0x32, 0x39, 0x2C, 0x35, 0x2E, 0x33, 0x37, 0x30, 0x35, -0x33, 0x20, 0x2D, 0x30, 0x2E, 0x32, 0x30, 0x33, 0x37, 0x34, 0x2C, 0x30, 0x2E, 0x32, 0x34, 0x35, -0x34, 0x39, 0x20, 0x2D, 0x30, 0x2E, 0x38, 0x38, 0x39, 0x30, 0x39, 0x2C, 0x30, 0x2E, 0x35, 0x34, -0x33, 0x36, 0x34, 0x20, 0x2D, 0x31, 0x2E, 0x35, 0x32, 0x33, 0x2C, 0x30, 0x2E, 0x36, 0x36, 0x32, -0x35, 0x37, 0x20, 0x2D, 0x30, 0x2E, 0x39, 0x38, 0x33, 0x31, 0x35, 0x2C, 0x30, 0x2E, 0x31, 0x38, -0x34, 0x34, 0x33, 0x20, 0x2D, 0x31, 0x2E, 0x32, 0x31, 0x35, 0x37, 0x39, 0x2C, 0x30, 0x2E, 0x34, -0x33, 0x32, 0x31, 0x33, 0x20, 0x2D, 0x31, 0x2E, 0x35, 0x38, 0x32, 0x36, 0x2C, 0x31, 0x2E, 0x36, -0x38, 0x35, 0x30, 0x33, 0x20, 0x2D, 0x31, 0x2E, 0x30, 0x37, 0x31, 0x36, 0x38, 0x2C, 0x33, 0x2E, -0x36, 0x36, 0x30, 0x34, 0x38, 0x20, 0x2D, 0x34, 0x2E, 0x35, 0x31, 0x30, 0x38, 0x2C, 0x37, 0x2E, -0x33, 0x38, 0x32, 0x33, 0x31, 0x20, 0x2D, 0x38, 0x2E, 0x30, 0x34, 0x32, 0x35, 0x39, 0x2C, 0x38, -0x2E, 0x37, 0x30, 0x33, 0x37, 0x32, 0x20, 0x2D, 0x32, 0x2E, 0x35, 0x32, 0x32, 0x33, 0x31, 0x2C, -0x30, 0x2E, 0x39, 0x34, 0x33, 0x37, 0x32, 0x20, 0x2D, 0x36, 0x2E, 0x30, 0x39, 0x36, 0x37, 0x34, -0x2C, 0x31, 0x2E, 0x32, 0x30, 0x32, 0x32, 0x31, 0x20, 0x2D, 0x38, 0x2E, 0x32, 0x30, 0x31, 0x33, -0x35, 0x2C, 0x30, 0x2E, 0x35, 0x39, 0x33, 0x31, 0x31, 0x20, 0x7A, 0x20, 0x6D, 0x20, 0x2D, 0x31, -0x33, 0x2E, 0x37, 0x36, 0x32, 0x32, 0x32, 0x2C, 0x2D, 0x32, 0x38, 0x2E, 0x39, 0x30, 0x36, 0x35, -0x20, 0x63, 0x20, 0x2D, 0x30, 0x2E, 0x30, 0x30, 0x32, 0x2C, 0x2D, 0x30, 0x2E, 0x38, 0x32, 0x34, -0x36, 0x32, 0x20, 0x2D, 0x30, 0x2E, 0x31, 0x30, 0x32, 0x32, 0x38, 0x2C, 0x2D, 0x32, 0x2E, 0x30, -0x39, 0x34, 0x36, 0x32, 0x20, 0x2D, 0x30, 0x2E, 0x32, 0x32, 0x32, 0x35, 0x34, 0x2C, 0x2D, 0x32, -0x2E, 0x38, 0x32, 0x32, 0x32, 0x32, 0x20, 0x6C, 0x20, 0x2D, 0x30, 0x2E, 0x32, 0x31, 0x38, 0x36, -0x37, 0x2C, 0x2D, 0x31, 0x2E, 0x33, 0x32, 0x32, 0x39, 0x32, 0x20, 0x68, 0x20, 0x31, 0x37, 0x2E, -0x33, 0x37, 0x33, 0x34, 0x32, 0x20, 0x31, 0x37, 0x2E, 0x33, 0x37, 0x33, 0x34, 0x31, 0x20, 0x6C, -0x20, 0x2D, 0x30, 0x2E, 0x32, 0x31, 0x32, 0x37, 0x31, 0x2C, 0x30, 0x2E, 0x37, 0x39, 0x33, 0x37, -0x35, 0x20, 0x63, 0x20, 0x2D, 0x30, 0x2E, 0x31, 0x31, 0x37, 0x2C, 0x30, 0x2E, 0x34, 0x33, 0x36, -0x35, 0x36, 0x20, 0x2D, 0x30, 0x2E, 0x32, 0x31, 0x34, 0x38, 0x39, 0x2C, 0x31, 0x2E, 0x37, 0x30, -0x36, 0x35, 0x36, 0x20, 0x2D, 0x30, 0x2E, 0x32, 0x31, 0x37, 0x35, 0x34, 0x2C, 0x32, 0x2E, 0x38, -0x32, 0x32, 0x32, 0x32, 0x20, 0x6C, 0x20, 0x2D, 0x30, 0x2E, 0x30, 0x30, 0x35, 0x2C, 0x32, 0x2E, -0x30, 0x32, 0x38, 0x34, 0x38, 0x20, 0x68, 0x20, 0x2D, 0x31, 0x36, 0x2E, 0x39, 0x33, 0x33, 0x31, -0x35, 0x20, 0x2D, 0x31, 0x36, 0x2E, 0x39, 0x33, 0x33, 0x33, 0x33, 0x20, 0x7A, 0x20, 0x6D, 0x20, -0x2D, 0x32, 0x2E, 0x31, 0x33, 0x32, 0x37, 0x39, 0x2C, 0x2D, 0x31, 0x31, 0x2E, 0x38, 0x31, 0x38, -0x30, 0x36, 0x20, 0x63, 0x20, 0x2D, 0x31, 0x2E, 0x37, 0x38, 0x35, 0x33, 0x32, 0x2C, 0x2D, 0x35, -0x2E, 0x34, 0x32, 0x38, 0x38, 0x39, 0x20, 0x2D, 0x35, 0x2E, 0x30, 0x36, 0x38, 0x31, 0x37, 0x2C, -0x2D, 0x31, 0x31, 0x2E, 0x34, 0x32, 0x38, 0x38, 0x34, 0x20, 0x2D, 0x38, 0x2E, 0x38, 0x38, 0x37, -0x36, 0x33, 0x2C, 0x2D, 0x31, 0x36, 0x2E, 0x32, 0x34, 0x33, 0x36, 0x20, 0x2D, 0x30, 0x2E, 0x39, -0x36, 0x38, 0x39, 0x2C, 0x2D, 0x31, 0x2E, 0x32, 0x32, 0x31, 0x33, 0x38, 0x20, 0x2D, 0x31, 0x2E, -0x36, 0x39, 0x33, 0x34, 0x33, 0x2C, 0x2D, 0x32, 0x2E, 0x32, 0x38, 0x38, 0x38, 0x39, 0x20, 0x2D, -0x31, 0x2E, 0x36, 0x31, 0x30, 0x30, 0x38, 0x2C, 0x2D, 0x32, 0x2E, 0x33, 0x37, 0x32, 0x32, 0x34, -0x20, 0x30, 0x2E, 0x30, 0x38, 0x33, 0x34, 0x2C, 0x2D, 0x30, 0x2E, 0x30, 0x38, 0x33, 0x34, 0x20, -0x35, 0x2E, 0x37, 0x37, 0x38, 0x30, 0x31, 0x2C, 0x2D, 0x32, 0x2E, 0x33, 0x38, 0x30, 0x37, 0x31, -0x20, 0x31, 0x32, 0x2E, 0x36, 0x35, 0x34, 0x37, 0x38, 0x2C, 0x2D, 0x35, 0x2E, 0x31, 0x30, 0x35, -0x32, 0x33, 0x20, 0x36, 0x2E, 0x38, 0x37, 0x36, 0x37, 0x37, 0x2C, 0x2D, 0x32, 0x2E, 0x37, 0x32, -0x34, 0x35, 0x32, 0x20, 0x31, 0x32, 0x2E, 0x38, 0x36, 0x30, 0x34, 0x31, 0x2C, 0x2D, 0x35, 0x2E, -0x31, 0x30, 0x36, 0x34, 0x32, 0x20, 0x31, 0x33, 0x2E, 0x32, 0x39, 0x36, 0x39, 0x37, 0x2C, 0x2D, -0x35, 0x2E, 0x32, 0x39, 0x33, 0x31, 0x31, 0x20, 0x6C, 0x20, 0x30, 0x2E, 0x37, 0x39, 0x33, 0x37, -0x35, 0x2C, 0x2D, 0x30, 0x2E, 0x33, 0x33, 0x39, 0x34, 0x34, 0x20, 0x76, 0x20, 0x31, 0x35, 0x2E, -0x38, 0x36, 0x37, 0x34, 0x34, 0x20, 0x31, 0x35, 0x2E, 0x38, 0x36, 0x37, 0x34, 0x33, 0x20, 0x68, -0x20, 0x2D, 0x37, 0x2E, 0x37, 0x33, 0x32, 0x33, 0x35, 0x20, 0x2D, 0x37, 0x2E, 0x37, 0x33, 0x32, -0x33, 0x35, 0x20, 0x7A, 0x20, 0x6D, 0x20, 0x32, 0x32, 0x2E, 0x38, 0x34, 0x30, 0x30, 0x37, 0x2C, -0x32, 0x2E, 0x31, 0x35, 0x33, 0x31, 0x36, 0x20, 0x63, 0x20, 0x2D, 0x30, 0x2E, 0x33, 0x34, 0x36, -0x38, 0x38, 0x2C, 0x2D, 0x30, 0x2E, 0x33, 0x34, 0x36, 0x38, 0x38, 0x20, 0x2D, 0x30, 0x2E, 0x33, -0x30, 0x30, 0x38, 0x38, 0x2C, 0x2D, 0x35, 0x30, 0x2E, 0x39, 0x32, 0x34, 0x36, 0x38, 0x20, 0x30, -0x2E, 0x30, 0x34, 0x36, 0x33, 0x2C, 0x2D, 0x35, 0x30, 0x2E, 0x39, 0x32, 0x34, 0x36, 0x38, 0x20, -0x30, 0x2E, 0x31, 0x35, 0x38, 0x37, 0x33, 0x2C, 0x30, 0x20, 0x33, 0x2E, 0x39, 0x32, 0x39, 0x30, -0x34, 0x2C, 0x31, 0x2E, 0x34, 0x33, 0x39, 0x31, 0x38, 0x20, 0x38, 0x2E, 0x33, 0x37, 0x38, 0x34, -0x37, 0x2C, 0x33, 0x2E, 0x31, 0x39, 0x38, 0x31, 0x39, 0x20, 0x34, 0x2E, 0x34, 0x34, 0x39, 0x34, -0x34, 0x2C, 0x31, 0x2E, 0x37, 0x35, 0x39, 0x20, 0x31, 0x31, 0x2E, 0x37, 0x34, 0x31, 0x31, 0x34, -0x2C, 0x34, 0x2E, 0x36, 0x33, 0x39, 0x34, 0x38, 0x20, 0x31, 0x36, 0x2E, 0x32, 0x30, 0x33, 0x37, -0x37, 0x2C, 0x36, 0x2E, 0x34, 0x30, 0x31, 0x30, 0x36, 0x20, 0x34, 0x2E, 0x34, 0x36, 0x32, 0x36, -0x34, 0x2C, 0x31, 0x2E, 0x37, 0x36, 0x31, 0x35, 0x38, 0x20, 0x38, 0x2E, 0x31, 0x35, 0x36, 0x33, -0x38, 0x2C, 0x33, 0x2E, 0x32, 0x33, 0x35, 0x36, 0x31, 0x20, 0x38, 0x2E, 0x32, 0x30, 0x38, 0x33, -0x2C, 0x33, 0x2E, 0x32, 0x37, 0x35, 0x36, 0x31, 0x20, 0x30, 0x2E, 0x31, 0x39, 0x32, 0x31, 0x31, -0x2C, 0x30, 0x2E, 0x31, 0x34, 0x38, 0x30, 0x33, 0x20, 0x2D, 0x30, 0x2E, 0x39, 0x37, 0x34, 0x38, -0x36, 0x2C, 0x35, 0x2E, 0x31, 0x31, 0x31, 0x30, 0x35, 0x20, 0x2D, 0x31, 0x2E, 0x37, 0x31, 0x32, -0x33, 0x33, 0x2C, 0x37, 0x2E, 0x32, 0x38, 0x32, 0x33, 0x33, 0x20, 0x2D, 0x31, 0x2E, 0x32, 0x30, -0x31, 0x2C, 0x33, 0x2E, 0x35, 0x33, 0x36, 0x30, 0x38, 0x20, 0x2D, 0x33, 0x2E, 0x30, 0x37, 0x39, -0x34, 0x37, 0x2C, 0x36, 0x2E, 0x38, 0x38, 0x32, 0x31, 0x39, 0x20, 0x2D, 0x36, 0x2E, 0x31, 0x31, -0x31, 0x39, 0x37, 0x2C, 0x31, 0x30, 0x2E, 0x38, 0x38, 0x37, 0x32, 0x35, 0x20, 0x2D, 0x35, 0x2E, -0x31, 0x30, 0x32, 0x33, 0x37, 0x2C, 0x36, 0x2E, 0x37, 0x33, 0x38, 0x37, 0x36, 0x20, 0x2D, 0x37, -0x2E, 0x31, 0x36, 0x38, 0x31, 0x38, 0x2C, 0x31, 0x30, 0x2E, 0x33, 0x36, 0x30, 0x39, 0x37, 0x20, -0x2D, 0x39, 0x2E, 0x33, 0x35, 0x35, 0x35, 0x38, 0x2C, 0x31, 0x36, 0x2E, 0x34, 0x30, 0x34, 0x31, -0x37, 0x20, 0x6C, 0x20, 0x2D, 0x31, 0x2E, 0x32, 0x37, 0x36, 0x39, 0x32, 0x2C, 0x33, 0x2E, 0x35, -0x32, 0x37, 0x37, 0x38, 0x20, 0x2D, 0x37, 0x2E, 0x30, 0x36, 0x38, 0x38, 0x38, 0x2C, 0x30, 0x2E, -0x30, 0x39, 0x35, 0x33, 0x20, 0x63, 0x20, 0x2D, 0x33, 0x2E, 0x38, 0x38, 0x37, 0x38, 0x39, 0x2C, -0x30, 0x2E, 0x30, 0x35, 0x32, 0x34, 0x20, 0x2D, 0x37, 0x2E, 0x31, 0x37, 0x37, 0x39, 0x32, 0x2C, -0x2D, 0x30, 0x2E, 0x30, 0x31, 0x33, 0x37, 0x20, 0x2D, 0x37, 0x2E, 0x33, 0x31, 0x31, 0x31, 0x37, -0x2C, 0x2D, 0x30, 0x2E, 0x31, 0x34, 0x36, 0x39, 0x39, 0x20, 0x7A, 0x20, 0x6D, 0x20, 0x2D, 0x33, -0x38, 0x2E, 0x31, 0x32, 0x34, 0x31, 0x2C, 0x2D, 0x32, 0x38, 0x2E, 0x39, 0x36, 0x34, 0x32, 0x37, -0x20, 0x63, 0x20, 0x2D, 0x36, 0x2E, 0x30, 0x32, 0x38, 0x31, 0x2C, 0x2D, 0x31, 0x35, 0x2E, 0x39, -0x31, 0x36, 0x38, 0x37, 0x20, 0x2D, 0x31, 0x2E, 0x31, 0x37, 0x38, 0x38, 0x37, 0x2C, 0x2D, 0x33, -0x33, 0x2E, 0x30, 0x35, 0x36, 0x36, 0x20, 0x31, 0x32, 0x2E, 0x32, 0x30, 0x35, 0x39, 0x39, 0x2C, -0x2D, 0x34, 0x33, 0x2E, 0x31, 0x34, 0x32, 0x33, 0x39, 0x39, 0x20, 0x34, 0x2E, 0x37, 0x38, 0x34, -0x34, 0x33, 0x2C, 0x2D, 0x33, 0x2E, 0x36, 0x30, 0x35, 0x31, 0x37, 0x37, 0x20, 0x31, 0x31, 0x2E, -0x38, 0x31, 0x39, 0x36, 0x34, 0x2C, 0x2D, 0x36, 0x2E, 0x35, 0x33, 0x32, 0x31, 0x39, 0x37, 0x20, -0x31, 0x37, 0x2E, 0x33, 0x30, 0x30, 0x32, 0x31, 0x2C, 0x2D, 0x37, 0x2E, 0x31, 0x39, 0x37, 0x37, -0x39, 0x38, 0x20, 0x6C, 0x20, 0x32, 0x2E, 0x30, 0x33, 0x31, 0x33, 0x33, 0x2C, 0x2D, 0x30, 0x2E, -0x32, 0x34, 0x36, 0x37, 0x20, 0x2D, 0x30, 0x2E, 0x30, 0x39, 0x31, 0x2C, 0x32, 0x30, 0x2E, 0x35, -0x33, 0x31, 0x37, 0x33, 0x37, 0x20, 0x2D, 0x30, 0x2E, 0x30, 0x39, 0x31, 0x31, 0x2C, 0x32, 0x30, -0x2E, 0x35, 0x33, 0x31, 0x37, 0x34, 0x20, 0x2D, 0x31, 0x34, 0x2E, 0x39, 0x39, 0x33, 0x30, 0x36, -0x2C, 0x35, 0x2E, 0x39, 0x35, 0x30, 0x37, 0x34, 0x20, 0x63, 0x20, 0x2D, 0x38, 0x2E, 0x32, 0x34, -0x36, 0x31, 0x38, 0x2C, 0x33, 0x2E, 0x32, 0x37, 0x32, 0x39, 0x31, 0x20, 0x2D, 0x31, 0x35, 0x2E, -0x30, 0x39, 0x38, 0x32, 0x34, 0x2C, 0x35, 0x2E, 0x39, 0x35, 0x31, 0x34, 0x36, 0x20, 0x2D, 0x31, -0x35, 0x2E, 0x32, 0x32, 0x36, 0x37, 0x39, 0x2C, 0x35, 0x2E, 0x39, 0x35, 0x32, 0x33, 0x34, 0x20, -0x2D, 0x30, 0x2E, 0x31, 0x32, 0x38, 0x35, 0x36, 0x2C, 0x38, 0x2E, 0x38, 0x65, 0x2D, 0x34, 0x20, -0x2D, 0x30, 0x2E, 0x36, 0x33, 0x39, 0x35, 0x37, 0x2C, 0x2D, 0x31, 0x2E, 0x30, 0x36, 0x39, 0x39, -0x37, 0x20, 0x2D, 0x31, 0x2E, 0x31, 0x33, 0x35, 0x35, 0x38, 0x2C, 0x2D, 0x32, 0x2E, 0x33, 0x37, -0x39, 0x36, 0x36, 0x20, 0x7A, 0x20, 0x6D, 0x20, 0x35, 0x34, 0x2E, 0x38, 0x31, 0x35, 0x31, 0x35, -0x2C, 0x2D, 0x32, 0x32, 0x2E, 0x35, 0x31, 0x30, 0x37, 0x35, 0x20, 0x63, 0x20, 0x2D, 0x38, 0x2E, -0x34, 0x34, 0x30, 0x32, 0x2C, 0x2D, 0x33, 0x2E, 0x33, 0x36, 0x36, 0x32, 0x31, 0x20, 0x2D, 0x31, -0x35, 0x2E, 0x37, 0x30, 0x33, 0x30, 0x32, 0x2C, 0x2D, 0x36, 0x2E, 0x32, 0x38, 0x32, 0x39, 0x35, -0x20, 0x2D, 0x31, 0x36, 0x2E, 0x31, 0x33, 0x39, 0x35, 0x38, 0x2C, 0x2D, 0x36, 0x2E, 0x34, 0x38, -0x31, 0x36, 0x33, 0x20, 0x6C, 0x20, 0x2D, 0x30, 0x2E, 0x37, 0x39, 0x33, 0x37, 0x35, 0x2C, 0x2D, -0x30, 0x2E, 0x33, 0x36, 0x31, 0x32, 0x34, 0x20, 0x56, 0x20, 0x39, 0x39, 0x2E, 0x31, 0x39, 0x30, -0x36, 0x30, 0x39, 0x20, 0x63, 0x20, 0x30, 0x2C, 0x2D, 0x39, 0x2E, 0x39, 0x33, 0x38, 0x39, 0x37, -0x39, 0x20, 0x30, 0x2E, 0x30, 0x33, 0x39, 0x33, 0x2C, 0x2D, 0x31, 0x30, 0x2E, 0x36, 0x30, 0x33, -0x38, 0x31, 0x35, 0x20, 0x30, 0x2E, 0x36, 0x31, 0x37, 0x33, 0x36, 0x2C, 0x2D, 0x31, 0x30, 0x2E, -0x34, 0x34, 0x34, 0x31, 0x36, 0x32, 0x20, 0x30, 0x2E, 0x33, 0x33, 0x39, 0x35, 0x35, 0x2C, 0x30, -0x2E, 0x30, 0x39, 0x33, 0x37, 0x38, 0x20, 0x31, 0x2E, 0x34, 0x31, 0x31, 0x31, 0x31, 0x2C, 0x30, -0x2E, 0x32, 0x37, 0x38, 0x36, 0x34, 0x20, 0x32, 0x2E, 0x33, 0x38, 0x31, 0x32, 0x35, 0x2C, 0x30, -0x2E, 0x34, 0x31, 0x30, 0x38, 0x30, 0x31, 0x20, 0x30, 0x2E, 0x39, 0x37, 0x30, 0x31, 0x34, 0x2C, -0x30, 0x2E, 0x31, 0x33, 0x32, 0x31, 0x36, 0x31, 0x20, 0x33, 0x2E, 0x30, 0x33, 0x33, 0x38, 0x39, -0x2C, 0x30, 0x2E, 0x36, 0x33, 0x38, 0x32, 0x31, 0x36, 0x20, 0x34, 0x2E, 0x35, 0x38, 0x36, 0x31, -0x31, 0x2C, 0x31, 0x2E, 0x31, 0x32, 0x34, 0x35, 0x36, 0x36, 0x20, 0x39, 0x2E, 0x37, 0x31, 0x36, -0x31, 0x37, 0x2C, 0x33, 0x2E, 0x30, 0x34, 0x34, 0x33, 0x32, 0x31, 0x20, 0x31, 0x38, 0x2E, 0x32, -0x35, 0x35, 0x33, 0x34, 0x2C, 0x31, 0x30, 0x2E, 0x36, 0x30, 0x39, 0x33, 0x33, 0x36, 0x20, 0x32, -0x32, 0x2E, 0x36, 0x30, 0x37, 0x30, 0x34, 0x2C, 0x32, 0x30, 0x2E, 0x30, 0x32, 0x38, 0x30, 0x33, -0x36, 0x20, 0x32, 0x2E, 0x30, 0x34, 0x38, 0x32, 0x32, 0x2C, 0x34, 0x2E, 0x34, 0x33, 0x33, 0x31, -0x31, 0x20, 0x33, 0x2E, 0x37, 0x32, 0x39, 0x31, 0x2C, 0x31, 0x32, 0x2E, 0x35, 0x38, 0x33, 0x33, -0x38, 0x20, 0x32, 0x2E, 0x35, 0x37, 0x37, 0x31, 0x2C, 0x31, 0x32, 0x2E, 0x34, 0x39, 0x35, 0x38, -0x39, 0x20, 0x2D, 0x30, 0x2E, 0x32, 0x36, 0x39, 0x33, 0x33, 0x2C, 0x2D, 0x30, 0x2E, 0x30, 0x32, -0x30, 0x35, 0x20, 0x2D, 0x37, 0x2E, 0x33, 0x39, 0x35, 0x33, 0x32, 0x2C, 0x2D, 0x32, 0x2E, 0x37, -0x39, 0x31, 0x33, 0x37, 0x20, 0x2D, 0x31, 0x35, 0x2E, 0x38, 0x33, 0x35, 0x35, 0x33, 0x2C, 0x2D, -0x36, 0x2E, 0x31, 0x35, 0x37, 0x35, 0x39, 0x20, 0x7A, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, -0x20, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x70, 0x61, 0x74, 0x68, 0x31, 0x22, 0x20, 0x2F, 0x3E, 0x3C, -0x2F, 0x67, 0x3E, 0x3C, 0x2F, 0x73, 0x76, 0x67, 0x3E, 0x0A - }; \ No newline at end of file diff --git a/src/www/colorpicker.html.unused b/src/www/colorpicker.html.unused new file mode 100644 index 0000000..674d0ee --- /dev/null +++ b/src/www/colorpicker.html.unused @@ -0,0 +1,147 @@ + + + + + BLLED Custom Colorpicker + + + + +

LED Farbe wΓ€hlen

+
+ +
+ + +

+
+
+
+
+
diff --git a/src/www/favicon.h b/src/www/favicon.h
deleted file mode 100644
index c6f156c..0000000
--- a/src/www/favicon.h
+++ /dev/null
@@ -1,278 +0,0 @@
-#include 
-//https://tomeko.net/online_tools/file_to_hex.php?lang=en
-const unsigned int BBLED_favicon_len = 4359; 
-const uint8_t BBLED_favicon[] PROGMEM = {
-0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, 
-0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x08, 0x06, 0x00, 0x00, 0x00, 0xE2, 0x98, 0x77, 
-0x38, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xAE, 0xCE, 0x1C, 0xE9, 0x00, 0x00, 
-0x10, 0xC1, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5E, 0xED, 0x9D, 0x7B, 0x90, 0x1C, 0xC5, 0x7D, 0xC7, 
-0x3F, 0xBF, 0x99, 0xDD, 0xDB, 0xD3, 0xDD, 0xE9, 0x85, 0x10, 0x6F, 0xDB, 0x18, 0x10, 0x21, 0x60, 
-0x20, 0x04, 0xFC, 0x20, 0x15, 0x6C, 0x11, 0x03, 0x41, 0xC2, 0xD2, 0x81, 0xE0, 0x0E, 0x2C, 0x2C, 
-0x90, 0x1D, 0x47, 0x18, 0x1C, 0x08, 0x94, 0xC1, 0xA6, 0x22, 0x4C, 0x2E, 0x8E, 0x71, 0xEC, 0x32, 
-0xB6, 0xCB, 0x60, 0x57, 0x8C, 0x52, 0x01, 0x0C, 0x92, 0xA0, 0xEE, 0xCA, 0x12, 0x3A, 0x21, 0x04, 
-0x22, 0x65, 0x29, 0x54, 0x62, 0x11, 0x61, 0x61, 0x1B, 0x2C, 0x15, 0x16, 0x46, 0x15, 0x5B, 0x80, 
-0x64, 0x0B, 0xF4, 0x3A, 0x49, 0xF7, 0x9A, 0x99, 0x5F, 0xAE, 0x67, 0x77, 0x4F, 0xBB, 0x7B, 0xBB, 
-0x3B, 0xB3, 0xBB, 0xB3, 0x0F, 0x52, 0xD7, 0xFF, 0xA8, 0x74, 0xD3, 0xD3, 0xD3, 0xFD, 0xFB, 0xF6, 
-0xEF, 0xD1, 0xBF, 0x47, 0xAF, 0x30, 0xDE, 0xEA, 0x4A, 0x01, 0xA9, 0xEB, 0xD7, 0xC7, 0x3F, 0xCE, 
-0x38, 0x00, 0x75, 0xDE, 0x04, 0xE3, 0x00, 0x8C, 0x03, 0x10, 0x40, 0x01, 0x45, 0x78, 0x74, 0x66, 
-0x82, 0xC9, 0x53, 0x5B, 0xE9, 0x1F, 0x3E, 0x8A, 0x98, 0x75, 0x3C, 0x43, 0x96, 0x45, 0x22, 0xFE, 
-0x0B, 0x3A, 0x7B, 0xF6, 0xFB, 0x6F, 0x77, 0x77, 0xD8, 0xD0, 0x7F, 0x22, 0xAE, 0x35, 0x0D, 0xDB, 
-0x7B, 0x97, 0x61, 0xED, 0xE3, 0x5D, 0xEF, 0x30, 0xB7, 0xAD, 0x1D, 0x02, 0xB4, 0xCE, 0x34, 0x2E, 
-0xFA, 0xF9, 0xC6, 0xE4, 0x00, 0x43, 0xF4, 0x9E, 0x8E, 0x56, 0x06, 0x07, 0x4F, 0x24, 0x26, 0x67, 
-0xA3, 0xFA, 0x31, 0x84, 0x8F, 0xA3, 0x9C, 0x86, 0x48, 0x1C, 0x74, 0x1B, 0xB6, 0x37, 0x97, 0xCE, 
-0xA7, 0xDF, 0xF2, 0x57, 0xF7, 0xC0, 0xAC, 0x04, 0x47, 0x27, 0x16, 0x81, 0xDE, 0xE3, 0x93, 0x5B, 
-0xD8, 0x0A, 0xFC, 0x37, 0x1E, 0x9B, 0x89, 0x0D, 0x6F, 0xC1, 0x6A, 0x7D, 0x9B, 0x8E, 0x9E, 0x43, 
-0x48, 0xE3, 0x81, 0xD1, 0x58, 0x00, 0x98, 0x9D, 0x3C, 0xE0, 0x4C, 0x23, 0xE6, 0x9E, 0x0B, 0x72, 
-0xB5, 0xA0, 0xED, 0x2A, 0x32, 0x09, 0x25, 0x0E, 0xD8, 0x80, 0xE5, 0x13, 0x5C, 0xD8, 0x02, 0xCC, 
-0xE2, 0xD3, 0xAB, 0x76, 0xF8, 0xFF, 0x7F, 0x66, 0x56, 0x82, 0x7D, 0x89, 0x9B, 0x11, 0xBD, 0x0F, 
-0x98, 0x80, 0xFA, 0x84, 0x76, 0x01, 0xC3, 0x01, 0x07, 0x80, 0x5E, 0x2C, 0x59, 0x81, 0xE7, 0xFD, 
-0x8A, 0x58, 0xE2, 0x1D, 0x3A, 0x7B, 0xCC, 0xB3, 0x86, 0x68, 0x8D, 0x01, 0x80, 0xD9, 0xF1, 0x4F, 
-0xCC, 0x99, 0x86, 0x5A, 0x1F, 0x01, 0xEE, 0xC4, 0xE2, 0x7C, 0x94, 0x09, 0x08, 0x31, 0xCC, 0xB3, 
-0xDC, 0x96, 0x0F, 0x80, 0x03, 0x89, 0x9B, 0x41, 0xEF, 0xC3, 0xA3, 0x25, 0xAB, 0xBB, 0xD9, 0xF5, 
-0x2A, 0x0E, 0xE8, 0x00, 0xF0, 0x4B, 0x70, 0xBF, 0x8D, 0x13, 0xFF, 0x1F, 0x16, 0xAC, 0xDC, 0xDD, 
-0x08, 0x1C, 0x51, 0x7F, 0x00, 0x1E, 0x99, 0xD9, 0x4C, 0xD3, 0x94, 0xB3, 0x10, 0x6F, 0x31, 0x2A, 
-0x97, 0x20, 0x3E, 0x01, 0xCD, 0x6E, 0x2F, 0xD6, 0xB6, 0x20, 0x39, 0x1C, 0x60, 0x00, 0x50, 0xBD, 
-0x0F, 0xCD, 0x01, 0x20, 0x73, 0x14, 0xC1, 0x45, 0x39, 0x0C, 0xFA, 0x02, 0x9E, 0xFE, 0x13, 0x4D, 
-0xCD, 0xBF, 0xA6, 0xB3, 0xA7, 0xBF, 0x9E, 0xAC, 0x50, 0x3F, 0x00, 0x7C, 0x39, 0x3F, 0xEB, 0x68, 
-0xDC, 0xF8, 0x1C, 0x54, 0xBE, 0x81, 0x30, 0x0D, 0x25, 0x56, 0x90, 0x18, 0x66, 0xA6, 0x47, 0xD4, 
-0xE9, 0x58, 0x00, 0xD2, 0x22, 0x48, 0x69, 0xF1, 0xBB, 0xA6, 0x57, 0x96, 0x4F, 0x05, 0x0B, 0x8E, 
-0x28, 0x7B, 0x14, 0xEE, 0xC5, 0xE9, 0x5F, 0xC9, 0x82, 0x75, 0x75, 0xE3, 0x86, 0xFA, 0x00, 0xD0, 
-0x35, 0x33, 0xC6, 0x8C, 0xD6, 0xF7, 0x23, 0xF6, 0xB7, 0x50, 0x99, 0x8D, 0xE5, 0xCB, 0xED, 0xF0, 
-0x73, 0x29, 0x24, 0x82, 0x82, 0x38, 0x20, 0xA9, 0x3F, 0x92, 0x40, 0x26, 0x15, 0x72, 0x3F, 0xCA, 
-0x5A, 0x62, 0xDE, 0x5D, 0x6C, 0xED, 0xDB, 0x41, 0xD7, 0x06, 0xA7, 0xD6, 0xDC, 0x10, 0x7E, 0xD1, 
-0x51, 0xCD, 0xAC, 0xBB, 0xA3, 0x89, 0xA1, 0xA1, 0xD3, 0xB0, 0xF8, 0x31, 0xC8, 0xB9, 0x23, 0x72, 
-0xDB, 0x28, 0xD8, 0xD0, 0x2D, 0x45, 0xBF, 0x82, 0x22, 0x48, 0x94, 0x96, 0x62, 0x76, 0x67, 0x36, 
-0x23, 0xF9, 0x88, 0x0C, 0x23, 0xFA, 0x32, 0xEA, 0x2D, 0x24, 0xF6, 0xC6, 0x76, 0x3A, 0xB7, 0x1A, 
-0xC5, 0x5D, 0xB3, 0x56, 0x5B, 0x00, 0x8C, 0xB9, 0x78, 0x4C, 0xF3, 0x0C, 0x3C, 0xAF, 0x1B, 0xF8, 
-0x93, 0x51, 0xAB, 0xA6, 0xD4, 0xE5, 0x56, 0xC2, 0x01, 0xF9, 0xBE, 0xE5, 0xEB, 0x06, 0x7D, 0x0D, 
-0x4F, 0x3A, 0x69, 0x6A, 0xFA, 0x2D, 0x9D, 0x3D, 0x35, 0x03, 0xA1, 0x76, 0x00, 0xA4, 0x77, 0xBE, 
-0xD0, 0x83, 0x70, 0x46, 0xD9, 0xC4, 0x4F, 0x4A, 0x91, 0x2D, 0x9A, 0xAB, 0x84, 0x33, 0x74, 0xC0, 
-0x28, 0x8D, 0xC7, 0x6E, 0xF7, 0x23, 0x22, 0x68, 0x2C, 0x10, 0x1E, 0xA2, 0xAF, 0xE2, 0x70, 0x2D, 
-0x87, 0xDF, 0xDA, 0xCE, 0x4D, 0x9B, 0x87, 0x4B, 0xDD, 0x17, 0xE5, 0xF4, 0xAF, 0x0D, 0x00, 0xBE, 
-0xCC, 0x6F, 0x39, 0x11, 0x89, 0x19, 0xB1, 0x73, 0x51, 0x51, 0xE2, 0xE7, 0x23, 0xDA, 0xD8, 0x95, 
-0x95, 0x65, 0x05, 0x05, 0x0E, 0x9D, 0xB4, 0x92, 0xD6, 0xA3, 0xC3, 0x9F, 0xE7, 0xF5, 0xC3, 0x6F, 
-0xD5, 0x42, 0x27, 0x54, 0x1F, 0x80, 0xAE, 0x2E, 0x8B, 0x73, 0x7E, 0x35, 0x95, 0x01, 0xFD, 0x07, 
-0xD0, 0xDB, 0xA0, 0x80, 0xA5, 0x13, 0x48, 0x9D, 0x23, 0x28, 0x84, 0xE6, 0x80, 0x72, 0xB6, 0x24, 
-0x98, 0x33, 0xC3, 0x0F, 0x41, 0xBF, 0xCE, 0xB6, 0xF3, 0xF7, 0xD0, 0xD5, 0xE5, 0x95, 0x37, 0x4C, 
-0xB8, 0xB7, 0xAA, 0x0F, 0xC0, 0x63, 0x97, 0xB5, 0xD2, 0x94, 0xB8, 0x04, 0x4F, 0x96, 0x81, 0xB4, 
-0x86, 0x9B, 0x56, 0x60, 0xAF, 0xA2, 0x66, 0x68, 0xE0, 0xDB, 0x41, 0x1D, 0xC4, 0x9C, 0x15, 0xB8, 
-0x11, 0x7B, 0xFF, 0xB3, 0x74, 0x6E, 0x38, 0x18, 0xD4, 0xBD, 0x92, 0xE7, 0xD5, 0x05, 0x60, 0xFD, 
-0xCC, 0x18, 0x3B, 0x27, 0x9E, 0x06, 0xD6, 0x53, 0x29, 0xA5, 0x5B, 0xC9, 0x5C, 0x33, 0xDF, 0xAD, 
-0x2E, 0x00, 0xFE, 0x97, 0x74, 0x3B, 0xE8, 0x5C, 0xFA, 0xDE, 0xDE, 0x56, 0x4D, 0x7D, 0x50, 0x4D, 
-0x00, 0x84, 0x65, 0x57, 0x4C, 0x41, 0x62, 0xB7, 0x03, 0x8B, 0x47, 0x4F, 0xB7, 0x25, 0x88, 0x9A, 
-0x82, 0x68, 0x45, 0x6D, 0x05, 0xF9, 0xD6, 0x68, 0x4A, 0x3F, 0x1F, 0xB1, 0x61, 0x8D, 0x3E, 0xF8, 
-0x1E, 0xF1, 0xA6, 0x7F, 0xA1, 0xA3, 0x67, 0x6F, 0xB5, 0xDC, 0x16, 0xD5, 0x03, 0xE0, 0xE7, 0x8B, 
-0xE2, 0xBC, 0xBE, 0xEB, 0x5C, 0x54, 0x9E, 0x05, 0xA6, 0xA5, 0xD6, 0x98, 0x3A, 0x03, 0x95, 0xE6, 
-0x23, 0xCE, 0x83, 0x59, 0x36, 0x07, 0x18, 0x0B, 0xCB, 0x1B, 0x5C, 0x84, 0xCA, 0xD7, 0x51, 0x26, 
-0xA5, 0x8E, 0x5B, 0xA5, 0x73, 0xDB, 0xD8, 0x0F, 0xED, 0x03, 0x77, 0x36, 0xB1, 0x09, 0x9B, 0xAB, 
-0x65, 0x9A, 0x56, 0x0F, 0x80, 0x65, 0x57, 0x4C, 0x45, 0x62, 0x5F, 0x06, 0xBE, 0x8C, 0x60, 0x8D, 
-0xBA, 0x11, 0x32, 0x17, 0x99, 0x3C, 0x91, 0x96, 0xD3, 0x72, 0x01, 0xB0, 0x71, 0xFA, 0x2F, 0x04, 
-0xDB, 0x7C, 0xEF, 0x3C, 0x60, 0x8A, 0xEF, 0x15, 0xCD, 0xF5, 0x29, 0x95, 0xC0, 0x7D, 0xA9, 0xAE, 
-0x8A, 0x7A, 0x0F, 0xE2, 0xC4, 0xBE, 0xC6, 0x8D, 0x2B, 0xF7, 0x54, 0x23, 0xB6, 0x50, 0xDE, 0xF2, 
-0x83, 0x48, 0x66, 0xDC, 0xCA, 0xCE, 0xC0, 0x19, 0x60, 0x3D, 0x0F, 0x1C, 0x3F, 0xA6, 0x7B, 0x09, 
-0x84, 0x28, 0xF0, 0xA9, 0x6C, 0x00, 0x7C, 0x91, 0xDD, 0x65, 0xF1, 0xF0, 0xCB, 0xAD, 0x34, 0x73, 
-0x1E, 0xB6, 0x5C, 0x83, 0xA7, 0x9F, 0x40, 0xE5, 0x44, 0x84, 0x36, 0xA0, 0xA9, 0x6C, 0xA8, 0x45, 
-0x77, 0xE3, 0x78, 0x97, 0xF2, 0xC6, 0xC1, 0x2D, 0xD5, 0x30, 0x4B, 0xAB, 0x03, 0x80, 0xB1, 0x7C, 
-0xEC, 0x96, 0xEB, 0x10, 0xFD, 0x57, 0xF0, 0x7D, 0xF9, 0xC9, 0x66, 0xE4, 0xAC, 0x96, 0x26, 0x7E, 
-0x42, 0x03, 0x90, 0xD9, 0xF1, 0xA1, 0x45, 0x71, 0xA6, 0xBE, 0x39, 0x0D, 0x27, 0xDE, 0x0E, 0xCC, 
-0x05, 0xCE, 0xF1, 0xB9, 0x42, 0x68, 0x1E, 0x75, 0xF8, 0x85, 0xD9, 0x04, 0x49, 0xEA, 0x18, 0xB3, 
-0xF4, 0x56, 0xEC, 0xC4, 0x52, 0x3A, 0x7B, 0x22, 0xB7, 0x88, 0xAA, 0x03, 0xC0, 0x23, 0xB3, 0x8F, 
-0x23, 0x11, 0x5F, 0x02, 0xCC, 0xC9, 0x24, 0x7E, 0xA9, 0xF1, 0xA8, 0x22, 0x34, 0x1A, 0xCB, 0x01, 
-0xF9, 0x90, 0x32, 0x0E, 0xBE, 0x25, 0x73, 0x26, 0x30, 0x49, 0x8C, 0xDB, 0xE3, 0x73, 0xC0, 0x45, 
-0xA8, 0xBC, 0x0F, 0xA1, 0x15, 0xCD, 0xE6, 0x0A, 0x11, 0x50, 0x2D, 0x70, 0x50, 0x16, 0x5D, 0x8B, 
-0xED, 0x7C, 0x8E, 0xCE, 0x67, 0x76, 0x05, 0x31, 0x7F, 0xA9, 0xCF, 0xA3, 0x07, 0xC0, 0x17, 0x3F, 
-0x83, 0x67, 0x81, 0xAC, 0x1F, 0x09, 0x16, 0x1E, 0x55, 0xEA, 0x84, 0x42, 0xF5, 0xCF, 0xB5, 0x82, 
-0x0C, 0xDD, 0xD6, 0xCF, 0xB4, 0x99, 0x78, 0xBA, 0xF0, 0xF4, 0x12, 0x97, 0x2E, 0xC6, 0x1E, 0x9E, 
-0xCC, 0xBC, 0xFA, 0x9D, 0x29, 0xC4, 0xDD, 0x59, 0xA2, 0xB2, 0x40, 0x2D, 0x35, 0x73, 0x9C, 0x0C, 
-0x19, 0x5C, 0x51, 0xF8, 0xE3, 0x7B, 0x40, 0x2F, 0x26, 0x96, 0xD8, 0x12, 0x75, 0x34, 0x2D, 0x7A, 
-0x00, 0x1E, 0x59, 0xD8, 0x4C, 0xF3, 0x5E, 0xC3, 0xFA, 0x3F, 0x46, 0x49, 0x64, 0xAD, 0x29, 0x8C, 
-0xD2, 0x0D, 0x27, 0x1A, 0xB2, 0x43, 0x92, 0xE6, 0xBC, 0xB1, 0x6B, 0xF2, 0xF9, 0xB8, 0x1A, 0x43, 
-0x63, 0xDB, 0x99, 0x32, 0xBC, 0x9F, 0xFE, 0xE6, 0xC1, 0x02, 0xC4, 0x12, 0xBA, 0x3B, 0xE2, 0x78, 
-0xCE, 0xC9, 0x78, 0xEE, 0x2D, 0x20, 0x7F, 0x85, 0x70, 0x12, 0xD0, 0x92, 0x0A, 0x7D, 0x26, 0xC3, 
-0x9E, 0x99, 0x4D, 0x18, 0xC4, 0xD3, 0x05, 0x0C, 0x1D, 0x58, 0xCD, 0x67, 0x37, 0x98, 0xC8, 0x5A, 
-0x64, 0x2D, 0x7A, 0x00, 0xBA, 0x3B, 0x26, 0xE3, 0x0E, 0xDF, 0x01, 0x7A, 0x6F, 0x81, 0x70, 0x62, 
-0xE5, 0x4A, 0xA0, 0x50, 0x4C, 0x18, 0xFD, 0x2A, 0xE8, 0x1F, 0x41, 0x1E, 0x04, 0xEF, 0xA7, 0x78, 
-0xCE, 0xDB, 0x34, 0xB5, 0x0D, 0xB0, 0xB5, 0xC7, 0xC9, 0xCB, 0x15, 0x46, 0x44, 0x3D, 0x3C, 0xB7, 
-0x8D, 0x16, 0x2E, 0x46, 0xB9, 0x1D, 0x7C, 0x51, 0x65, 0xB8, 0x22, 0x81, 0x60, 0x8F, 0xCE, 0xDF, 
-0x0F, 0x6B, 0xEA, 0x62, 0xBC, 0xE1, 0x1F, 0xF2, 0x99, 0xB5, 0x26, 0xC6, 0x1C, 0x59, 0x8B, 0x1E, 
-0x80, 0xC7, 0xAE, 0x3A, 0x86, 0xB8, 0xFB, 0x03, 0x54, 0x3A, 0x52, 0x7A, 0x37, 0x5B, 0xF4, 0x87, 
-0xD9, 0xE1, 0x41, 0xCB, 0x0B, 0x8A, 0x09, 0x27, 0x9D, 0x6A, 0x7D, 0xA8, 0xFE, 0x94, 0x18, 0xDF, 
-0xC7, 0xE5, 0x37, 0x0C, 0x1E, 0xB5, 0x9F, 0xD6, 0x43, 0xC3, 0x05, 0x45, 0x88, 0xE1, 0xA2, 0xDD, 
-0x2D, 0x26, 0x42, 0x77, 0x3B, 0xEA, 0x2B, 0x6E, 0x63, 0xBD, 0x99, 0xF0, 0xA8, 0x89, 0x4B, 0x1B, 
-0xAE, 0x78, 0x14, 0xF1, 0xEE, 0x62, 0xFE, 0xEA, 0x77, 0x82, 0xA6, 0x57, 0xCA, 0xF3, 0xE8, 0x01, 
-0x58, 0x3A, 0xEF, 0x24, 0x2C, 0x67, 0x25, 0xC8, 0x05, 0x81, 0x13, 0x49, 0x83, 0x91, 0xFA, 0xB7, 
-0x10, 0x36, 0x63, 0xFE, 0x5E, 0x2C, 0x2B, 0xC2, 0xC4, 0x84, 0x8F, 0x8C, 0x6B, 0xF2, 0x23, 0x8C, 
-0x5B, 0x79, 0x27, 0xE8, 0x83, 0x38, 0xBA, 0x82, 0xE6, 0xE6, 0xDD, 0xEC, 0xDD, 0x3E, 0xC8, 0xA2, 
-0xCD, 0x4E, 0xC1, 0xD3, 0xAD, 0x6F, 0xC5, 0x35, 0x7F, 0x64, 0x24, 0x58, 0xB3, 0x58, 0x84, 0x33, 
-0xD5, 0x58, 0x50, 0xCA, 0xCF, 0xF0, 0xEC, 0x05, 0x2C, 0x58, 0xB1, 0x33, 0x70, 0x5D, 0x25, 0x74, 
-0x88, 0x1E, 0x80, 0x27, 0xAE, 0x3C, 0x19, 0x74, 0x3D, 0xCA, 0xC9, 0x79, 0x2D, 0xA0, 0x5C, 0x6A, 
-0x16, 0xE1, 0x88, 0x82, 0x80, 0x08, 0x5B, 0xB4, 0x50, 0x5A, 0x4A, 0x4E, 0x50, 0x3E, 0x63, 0x0C, 
-0x03, 0xC6, 0x41, 0x2C, 0x79, 0x09, 0x9C, 0x7F, 0x66, 0xA8, 0xFF, 0x55, 0x06, 0x4E, 0x3D, 0xC0, 
-0xCE, 0x13, 0x46, 0x94, 0x76, 0x01, 0x8F, 0x67, 0xD2, 0xA0, 0x38, 0xDA, 0xB7, 0xA0, 0x84, 0x8F, 
-0x32, 0x6C, 0x2F, 0xE2, 0x86, 0x95, 0x7F, 0x2C, 0x81, 0xBE, 0x81, 0x5D, 0xA3, 0x07, 0xA0, 0x7B, 
-0xCE, 0x07, 0x71, 0xAD, 0x8D, 0x28, 0xC7, 0x16, 0xFB, 0x7A, 0x45, 0x92, 0xA8, 0x52, 0x5F, 0x90, 
-0xA8, 0x89, 0xFD, 0xBE, 0x8D, 0xB2, 0x0C, 0xB1, 0x96, 0x60, 0xC7, 0xFF, 0xE0, 0xE7, 0x10, 0x75, 
-0xF4, 0x78, 0x05, 0xB9, 0xC2, 0x44, 0xF3, 0xF6, 0x7C, 0x74, 0x38, 0x6A, 0xF7, 0x74, 0xF4, 0x00, 
-0x2C, 0xBB, 0xE2, 0x14, 0xC4, 0x7E, 0x11, 0x64, 0x7A, 0x1E, 0x6B, 0x22, 0x4B, 0x01, 0x57, 0x00, 
-0x42, 0x70, 0x56, 0x44, 0xE0, 0xDE, 0x1B, 0xED, 0x70, 0x10, 0xE4, 0x97, 0x78, 0xEE, 0xB7, 0x70, 
-0x0F, 0x6F, 0x64, 0xC2, 0x51, 0xFB, 0xE8, 0xEC, 0x31, 0x66, 0x6C, 0x4D, 0x52, 0x1A, 0xA3, 0x07, 
-0x20, 0x83, 0x03, 0xF2, 0x12, 0x38, 0x88, 0xEA, 0x41, 0xCF, 0x93, 0x9A, 0xBD, 0x70, 0x66, 0x5C, 
-0xB1, 0xBC, 0xA0, 0xC2, 0xA0, 0x18, 0x7B, 0xC8, 0x43, 0x79, 0x13, 0xD1, 0xD5, 0x88, 0xF3, 0x20, 
-0x56, 0xEB, 0x0E, 0x3A, 0x7A, 0x06, 0xAA, 0xE5, 0x05, 0x4D, 0x4F, 0x25, 0x7A, 0x00, 0x96, 0xCD, 
-0xFB, 0x00, 0x96, 0xBB, 0x21, 0x4B, 0x07, 0x14, 0x58, 0x78, 0x3E, 0x5A, 0x07, 0xD2, 0x3F, 0x39, 
-0xE3, 0x8A, 0x00, 0x28, 0xF8, 0x0D, 0xDF, 0xDC, 0x34, 0x3B, 0x5F, 0x8D, 0xCB, 0xE1, 0x15, 0x5F, 
-0x3C, 0xA9, 0xB7, 0x8E, 0xBE, 0xB7, 0xF6, 0x54, 0x2B, 0x26, 0x10, 0x3D, 0x00, 0xBE, 0x15, 0xE4, 
-0x9A, 0x00, 0xCC, 0xF9, 0xE1, 0xA5, 0x40, 0xC8, 0x9E, 0x49, 0x02, 0x0D, 0x60, 0xE9, 0x4B, 0x58, 
-0xC3, 0xD7, 0xD0, 0xB9, 0x76, 0xB7, 0xFF, 0xA6, 0xC9, 0x0D, 0x0D, 0x93, 0x19, 0x17, 0xF2, 0x33, 
-0xA9, 0x6E, 0x46, 0x1F, 0x38, 0x28, 0x3B, 0x10, 0x9E, 0xC7, 0x71, 0x7F, 0xC4, 0x34, 0xF7, 0x35, 
-0x66, 0xAF, 0x1D, 0x2C, 0x6D, 0x98, 0xE2, 0xBD, 0xA3, 0x07, 0xC0, 0x9C, 0x03, 0x62, 0xDE, 0x8F, 
-0x80, 0xAB, 0x32, 0xD9, 0x2C, 0x4B, 0xA0, 0x06, 0x6E, 0xF3, 0x9C, 0x49, 0x1B, 0xA5, 0xA9, 0xEC, 
-0x05, 0xD6, 0xE3, 0xE9, 0xE3, 0xBE, 0xAC, 0xBE, 0xE1, 0xA2, 0x91, 0x20, 0x49, 0xCA, 0x7A, 0x89, 
-0x10, 0x80, 0x3C, 0x53, 0x4B, 0x27, 0xFA, 0x3E, 0x4E, 0xAC, 0xE9, 0x4E, 0x3A, 0x7B, 0x8C, 0x5B, 
-0x3A, 0xB2, 0x16, 0x3D, 0x00, 0xE6, 0x24, 0xEC, 0x0C, 0xDD, 0x8D, 0xF0, 0x95, 0x50, 0xD9, 0x6E, 
-0x85, 0xC1, 0x30, 0x72, 0xF9, 0x10, 0xCA, 0x6F, 0x41, 0x97, 0xE3, 0xC9, 0xB3, 0x78, 0xFD, 0xDB, 
-0x79, 0xDF, 0xD0, 0x20, 0x33, 0x37, 0xB8, 0x59, 0xB2, 0x39, 0x1F, 0x00, 0xA5, 0x82, 0x5C, 0xD4, 
-0x64, 0x33, 0x6E, 0x3A, 0xEE, 0xA5, 0x85, 0xEF, 0xD3, 0xDE, 0xDB, 0x17, 0x19, 0xF5, 0xCB, 0xF6, 
-0x91, 0x17, 0x9B, 0x41, 0x77, 0xC7, 0x04, 0x9C, 0xC1, 0x4E, 0x44, 0x96, 0xA4, 0x3C, 0x8E, 0xA3, 
-0xE7, 0xA2, 0x90, 0x13, 0x1F, 0x46, 0x79, 0x07, 0xD1, 0x75, 0x08, 0x2B, 0xB0, 0x87, 0x37, 0xD2, 
-0xC6, 0x01, 0x36, 0x15, 0x31, 0x01, 0x33, 0xD3, 0xD3, 0x53, 0x4A, 0x38, 0x14, 0xFD, 0x53, 0xEE, 
-0x71, 0x33, 0xAF, 0x00, 0x93, 0x67, 0x00, 0xE4, 0x46, 0xA6, 0x0C, 0xAE, 0x6A, 0x7C, 0x11, 0x64, 
-0x72, 0x80, 0x4E, 0x9F, 0xFA, 0x61, 0xF0, 0x9E, 0x49, 0x45, 0xA6, 0xC6, 0x5A, 0xA3, 0x46, 0xCD, 
-0x65, 0xF3, 0x9E, 0x59, 0x7F, 0x1F, 0xA2, 0x5B, 0x51, 0x56, 0xE0, 0xC9, 0x1A, 0x9A, 0x9A, 0x7E, 
-0x1F, 0x78, 0x62, 0x4D, 0x8F, 0x9C, 0x07, 0x80, 0x40, 0xB0, 0x4B, 0x38, 0x10, 0x02, 0xEF, 0x62, 
-0xB9, 0x9F, 0xE4, 0xDA, 0x0B, 0x5E, 0x1D, 0x15, 0x7B, 0x81, 0x1F, 0x08, 0xD7, 0x21, 0x7A, 0x11, 
-0x64, 0x8C, 0xC4, 0xEE, 0x4F, 0x9D, 0x80, 0x6B, 0xF5, 0xA2, 0xF2, 0xE7, 0xF9, 0xA6, 0x91, 0xB1, 
-0x76, 0x93, 0x02, 0x68, 0x9C, 0x67, 0xEB, 0xC0, 0x79, 0x8A, 0x01, 0xF7, 0x45, 0xA4, 0xBF, 0x8F, 
-0xDF, 0xCD, 0x1C, 0xCA, 0x7B, 0xE0, 0xE9, 0xC2, 0xE2, 0xB4, 0x59, 0x6D, 0xC4, 0x12, 0xD3, 0xD9, 
-0xEF, 0xEE, 0xE4, 0xA6, 0xD5, 0x26, 0x7D, 0xA4, 0x5A, 0x4A, 0x38, 0x63, 0xEA, 0x6A, 0x22, 0x7B, 
-0x0B, 0x98, 0xDF, 0x6B, 0x0E, 0x6C, 0x91, 0xB6, 0x6A, 0x00, 0x00, 0x4B, 0x67, 0x4D, 0xC2, 0x8E, 
-0xDF, 0x81, 0xCA, 0xBD, 0x26, 0x0B, 0x2E, 0x73, 0xB3, 0x89, 0xE0, 0xAA, 0x72, 0x00, 0x91, 0x57, 
-0x50, 0x6F, 0x0D, 0x96, 0xB3, 0x8A, 0x43, 0xB1, 0x9D, 0x9C, 0x72, 0xA0, 0x9F, 0x8B, 0x0B, 0x64, 
-0x27, 0x9B, 0x1D, 0x7E, 0xD0, 0x3E, 0x16, 0x37, 0xF6, 0x09, 0xF0, 0xAE, 0x44, 0x65, 0x3A, 0xAE, 
-0x7D, 0xED, 0xA8, 0x5F, 0xA6, 0x52, 0x25, 0x9C, 0x76, 0x93, 0xA7, 0x26, 0x9A, 0xC5, 0x1C, 0xC6, 
-0x12, 0xF2, 0xF4, 0x0E, 0xF6, 0x1D, 0x78, 0x94, 0x2F, 0x46, 0x9F, 0x23, 0x54, 0x1D, 0x00, 0x4C, 
-0x48, 0xB0, 0x6D, 0xD7, 0x85, 0x08, 0xAB, 0x05, 0x99, 0xE4, 0x4B, 0x1C, 0xA1, 0x5F, 0x55, 0x77, 
-0xA1, 0xF2, 0x02, 0x98, 0xFC, 0x50, 0x6F, 0x13, 0x83, 0x7D, 0x07, 0x59, 0xB8, 0x61, 0x30, 0xEF, 
-0x61, 0xC7, 0xF8, 0x61, 0x0E, 0x0D, 0x4F, 0x24, 0xE1, 0x7C, 0x08, 0xB1, 0x2E, 0x43, 0xE5, 0x9A, 
-0x91, 0xF8, 0xD6, 0x09, 0xC9, 0x02, 0x0C, 0xDD, 0x86, 0x48, 0x76, 0x89, 0x52, 0xF4, 0x66, 0x68, 
-0x6A, 0xA7, 0xAB, 0xA9, 0x1D, 0xF8, 0x6B, 0xEC, 0xC4, 0x2B, 0x51, 0x07, 0x63, 0xCC, 0x07, 0xAA, 
-0x03, 0x80, 0xB1, 0x5F, 0x1E, 0xBF, 0x6A, 0x3A, 0x31, 0xF7, 0xDF, 0x10, 0x2E, 0x04, 0xD9, 0x82, 
-0xE8, 0x33, 0xA8, 0xD5, 0x43, 0x8B, 0xF7, 0x2E, 0x93, 0x8A, 0xEC, 0x76, 0xA3, 0xC4, 0x87, 0x0F, 
-0x1F, 0x8F, 0xD8, 0x7F, 0x81, 0x70, 0x2D, 0x2A, 0x1F, 0x06, 0x3F, 0xD5, 0xC4, 0x04, 0x77, 0x0A, 
-0xD7, 0x88, 0x45, 0x09, 0xC0, 0x91, 0xC0, 0x91, 0x49, 0xD8, 0xFD, 0x77, 0xEC, 0xC1, 0xBB, 0xE9, 
-0x7C, 0x2E, 0x52, 0xF3, 0x33, 0xD3, 0x44, 0x8F, 0x54, 0xA6, 0x8D, 0x0E, 0xE6, 0xE7, 0xEA, 0xF4, 
-0xFF, 0x29, 0xCA, 0xD1, 0xF4, 0xBB, 0xAF, 0xF8, 0xB2, 0xBD, 0xD8, 0x6E, 0x37, 0x81, 0x10, 0x77, 
-0xE8, 0x2C, 0xE0, 0x72, 0x94, 0xAB, 0x11, 0x8E, 0xF3, 0x77, 0x7B, 0xFE, 0x3A, 0xB1, 0xB2, 0x92, 
-0x73, 0x83, 0x16, 0x9A, 0xC7, 0x72, 0xDA, 0x87, 0x6A, 0x3B, 0xF1, 0xC4, 0x8B, 0xEF, 0xBD, 0xBC, 
-0x20, 0x5F, 0x19, 0x77, 0x24, 0x77, 0x6C, 0xBE, 0xAA, 0xC4, 0x74, 0xC0, 0xBC, 0x4D, 0x4F, 0x44, 
-0x4C, 0xEC, 0xC0, 0x32, 0x41, 0xF3, 0x73, 0x10, 0x26, 0xFA, 0xBB, 0x3D, 0x19, 0x04, 0x29, 0xD4, 
-0x2A, 0x07, 0x20, 0x38, 0x3C, 0x6A, 0xCE, 0x1A, 0x0F, 0x63, 0x0F, 0xDC, 0x4D, 0xC7, 0x73, 0xEF, 
-0xC1, 0xCC, 0xB8, 0xFC, 0xA4, 0x13, 0x1E, 0x5A, 0x14, 0x23, 0xBE, 0x63, 0x0A, 0x4D, 0xB1, 0x53, 
-0xB1, 0xAD, 0xAB, 0x51, 0x9D, 0x07, 0x62, 0x7C, 0xEE, 0x26, 0x71, 0x37, 0x7F, 0x71, 0xDE, 0xD8, 
-0xAD, 0x59, 0x3E, 0x00, 0xA1, 0x0E, 0x08, 0x20, 0xA2, 0x6F, 0xA9, 0xE3, 0x5D, 0xC1, 0xE1, 0x9D, 
-0x5B, 0xAB, 0xE5, 0x07, 0xAA, 0x9E, 0x0E, 0xC8, 0x25, 0xBE, 0x31, 0x1F, 0xCF, 0xEC, 0x68, 0x81, 
-0xC1, 0xE3, 0x70, 0xC5, 0xF8, 0x88, 0xFE, 0x1E, 0xE5, 0x54, 0x3F, 0xFE, 0x2A, 0x34, 0x85, 0x3A, 
-0x31, 0x67, 0x8E, 0x59, 0xBC, 0x4E, 0xD8, 0x04, 0xD7, 0xCB, 0x6A, 0xA3, 0xD8, 0x98, 0xEC, 0x68, 
-0xE1, 0x66, 0x86, 0xFA, 0x7F, 0xC2, 0x0D, 0xEB, 0x0E, 0x95, 0x35, 0x58, 0xC8, 0x97, 0xAA, 0xA3, 
-0x84, 0x73, 0x3F, 0x6E, 0xF4, 0x81, 0x33, 0x7C, 0x0B, 0x78, 0xB7, 0x0A, 0x32, 0x5D, 0x95, 0x56, 
-0x3F, 0x5D, 0xB1, 0xD0, 0x6E, 0x4C, 0xCF, 0x2A, 0x87, 0x90, 0x19, 0xDD, 0x23, 0xCB, 0x8E, 0xCE, 
-0x31, 0x39, 0x4D, 0x72, 0x90, 0x09, 0x55, 0xAE, 0x44, 0xF5, 0x96, 0xFF, 0x1F, 0xF5, 0x01, 0x06, 
-0x0C, 0xDF, 0x2C, 0x7D, 0xF3, 0x2C, 0x24, 0x6E, 0x12, 0x75, 0x8B, 0x46, 0xCA, 0x42, 0xFA, 0x2D, 
-0xCA, 0x17, 0x41, 0x19, 0x85, 0x92, 0xB9, 0xFB, 0x44, 0x50, 0x55, 0xE4, 0x75, 0x1C, 0xEF, 0x72, 
-0xB6, 0xD7, 0xA6, 0x6A, 0xB2, 0x36, 0x1C, 0xE0, 0x83, 0x30, 0xA7, 0x85, 0x49, 0x72, 0x89, 0xA8, 
-0x2C, 0x55, 0x7C, 0x45, 0x5B, 0x49, 0x8B, 0x8C, 0x03, 0xB2, 0x27, 0xA1, 0xBB, 0xB1, 0xBC, 0xCB, 
-0xB1, 0x26, 0x98, 0x02, 0xEE, 0x9A, 0x14, 0xEA, 0xD5, 0x0E, 0x00, 0xBF, 0x30, 0xFB, 0x92, 0x49, 
-0x38, 0x2D, 0x8B, 0x41, 0x4C, 0xCD, 0x40, 0x56, 0xCE, 0x68, 0x18, 0xB9, 0x5D, 0x54, 0x04, 0x85, 
-0x3D, 0x07, 0x14, 0x16, 0x7B, 0x87, 0xF1, 0xF4, 0x6F, 0x88, 0x27, 0x56, 0xD5, 0xB2, 0x7A, 0xBE, 
-0x76, 0x00, 0x98, 0xAD, 0x66, 0xEA, 0xC5, 0xCE, 0xDC, 0x74, 0x0C, 0x4E, 0xEC, 0x39, 0x90, 0xB3, 
-0x33, 0x0F, 0x82, 0xA1, 0x8C, 0x93, 0x74, 0xA7, 0x4A, 0x83, 0xF2, 0x99, 0xA7, 0xA0, 0xA4, 0x9E, 
-0x71, 0x11, 0x59, 0x41, 0x33, 0x8B, 0xB8, 0xF2, 0xA9, 0xFD, 0xD5, 0x0E, 0x43, 0x66, 0xDB, 0x13, 
-0x95, 0x08, 0x82, 0x72, 0xDE, 0x35, 0x09, 0x50, 0x6F, 0x4F, 0x39, 0x17, 0xF1, 0x1D, 0x5C, 0x53, 
-0xCB, 0x19, 0xC2, 0x0F, 0x49, 0x96, 0x73, 0x57, 0x44, 0xA1, 0x8F, 0x09, 0x3B, 0x40, 0x3E, 0x8E, 
-0x1D, 0xDF, 0x51, 0x0D, 0x77, 0x43, 0xB1, 0x35, 0xD6, 0x96, 0x03, 0xD2, 0x33, 0x49, 0xC6, 0x0C, 
-0xBA, 0x40, 0xBE, 0x54, 0xF4, 0x62, 0x8E, 0xC2, 0x6C, 0x11, 0x89, 0x0E, 0x48, 0x0D, 0x3F, 0x84, 
-0xF0, 0x59, 0x66, 0x1C, 0xDB, 0xC3, 0x05, 0x4B, 0x6A, 0x52, 0x1B, 0x5C, 0x5F, 0x0E, 0xF0, 0x45, 
-0x91, 0x39, 0x17, 0xCC, 0x3E, 0x06, 0x27, 0xBE, 0x71, 0x24, 0xE5, 0xEF, 0x48, 0x02, 0x57, 0x58, 
-0x76, 0x28, 0x22, 0x82, 0x72, 0xAF, 0x2A, 0x28, 0x88, 0x61, 0xB2, 0x26, 0xCC, 0x98, 0x3D, 0x9B, 
-0x19, 0x94, 0x4B, 0x59, 0x58, 0x5B, 0xD1, 0x93, 0x29, 0x05, 0xC3, 0x2E, 0x3B, 0xDA, 0x7E, 0x26, 
-0x70, 0x73, 0xDA, 0xA4, 0xCF, 0x63, 0xCB, 0x83, 0x45, 0x6F, 0x49, 0xC9, 0x67, 0x36, 0x06, 0xE5, 
-0x86, 0x86, 0x9E, 0xA9, 0x0E, 0x20, 0xD6, 0xA7, 0xF8, 0xCD, 0x9F, 0xAD, 0x8F, 0x3A, 0xE1, 0x2A, 
-0xEC, 0x14, 0xEA, 0x23, 0x82, 0xCC, 0xEC, 0x92, 0xD7, 0x92, 0x4D, 0xC5, 0x19, 0xDA, 0x88, 0x30, 
-0xA3, 0xA4, 0xD3, 0x70, 0x11, 0x00, 0xC4, 0x2B, 0x7E, 0x59, 0x47, 0x06, 0x61, 0x4C, 0xD6, 0xC3, 
-0x26, 0xEC, 0xFD, 0x97, 0x56, 0xBB, 0x16, 0xB8, 0xF1, 0x74, 0x40, 0x7A, 0x46, 0x46, 0x14, 0x9D, 
-0x31, 0xF7, 0x56, 0x3C, 0xEB, 0xDB, 0x25, 0xDD, 0x9A, 0x12, 0x92, 0x03, 0xC6, 0x88, 0x9F, 0xAC, 
-0x3F, 0xA8, 0x89, 0x43, 0x74, 0x72, 0x5D, 0xEF, 0xEA, 0x5A, 0x5A, 0x3D, 0x63, 0x0F, 0x7F, 0x61, 
-0x79, 0xA5, 0x5A, 0xFD, 0x92, 0x69, 0x2C, 0x9B, 0x46, 0x3C, 0x8F, 0xEF, 0x2F, 0x81, 0x0B, 0xCA, 
-0xB7, 0x82, 0x7C, 0x10, 0xC4, 0xF8, 0xF9, 0xB7, 0x62, 0x1F, 0xFA, 0x4B, 0x3A, 0xFF, 0x23, 0x79, 
-0xF3, 0x62, 0x9D, 0x5A, 0xFD, 0x44, 0x50, 0x7A, 0xC1, 0xA6, 0xBA, 0xF1, 0x89, 0x5F, 0x3C, 0x84, 
-0xB0, 0x30, 0x48, 0x17, 0xF8, 0xAF, 0x24, 0x77, 0x71, 0x51, 0x00, 0x82, 0xCF, 0x14, 0x32, 0x8C, 
-0x7A, 0xF7, 0x71, 0x7D, 0xEF, 0xD7, 0x82, 0x13, 0x22, 0xAA, 0x8B, 0x4C, 0xFD, 0x01, 0x30, 0xEB, 
-0x5B, 0x76, 0xE5, 0xF9, 0x88, 0xF7, 0x9F, 0x45, 0xEF, 0x92, 0xC8, 0xA6, 0x6A, 0x25, 0x1C, 0x60, 
-0xB2, 0xEB, 0xF6, 0xA1, 0xCE, 0x05, 0x5C, 0xBF, 0x66, 0x7B, 0x75, 0xC9, 0x1B, 0x3C, 0x7A, 0x63, 
-0x00, 0x90, 0x0C, 0xE2, 0xBF, 0x80, 0xCA, 0x87, 0x02, 0xEF, 0x11, 0x4A, 0xCE, 0xD8, 0xE4, 0x86, 
-0xCE, 0x1E, 0x73, 0x6D, 0xA5, 0xB9, 0xE1, 0x24, 0x59, 0xD5, 0x32, 0xB6, 0x1D, 0x39, 0x45, 0x9B, 
-0xEA, 0x99, 0x97, 0xE8, 0xF3, 0x2E, 0x19, 0xCD, 0xAA, 0x08, 0xA6, 0x53, 0xD5, 0x7A, 0x34, 0x06, 
-0x00, 0xFE, 0xB5, 0x95, 0x73, 0xEF, 0x47, 0xE4, 0x32, 0x14, 0x7B, 0x4C, 0xA4, 0x3A, 0xED, 0x96, 
-0x1E, 0x25, 0xA2, 0xBE, 0x81, 0xED, 0xFC, 0xED, 0x68, 0xD9, 0xA8, 0xEF, 0xEE, 0xEE, 0xBF, 0x1E, 
-0xEC, 0xDB, 0x90, 0x02, 0x85, 0x81, 0xA6, 0x04, 0x35, 0x59, 0x8A, 0xEA, 0x20, 0xDA, 0xCD, 0xA7, 
-0x7B, 0x0D, 0x58, 0x75, 0x6F, 0x8D, 0x01, 0x80, 0x21, 0x83, 0x29, 0x80, 0x38, 0xAE, 0x2D, 0x4E, 
-0xDF, 0x60, 0xF0, 0x9C, 0x26, 0x26, 0x4C, 0x81, 0xC5, 0x50, 0x86, 0xDB, 0x40, 0xF8, 0xF9, 0xA2, 
-0x18, 0xDB, 0xF7, 0x26, 0x02, 0xDF, 0x9F, 0x98, 0x30, 0x70, 0x9A, 0x77, 0x6B, 0xE2, 0xED, 0x0C, 
-0x42, 0x38, 0x78, 0xB1, 0x41, 0x23, 0x8C, 0x3F, 0xAF, 0x88, 0x02, 0xE3, 0x00, 0x54, 0x44, 0xBE, 
-0xCA, 0x5F, 0x6E, 0x1C, 0x00, 0x8C, 0x1E, 0x78, 0xB2, 0xFD, 0x24, 0x6C, 0x6D, 0xC1, 0xC9, 0xC9, 
-0x1C, 0xAD, 0x7C, 0x9D, 0xC9, 0x11, 0x5C, 0x51, 0x12, 0xDE, 0xC1, 0xD1, 0x4B, 0xBF, 0xA3, 0x1A, 
-0xB7, 0x82, 0x71, 0x1A, 0x07, 0x80, 0x6E, 0x6C, 0x9C, 0xF6, 0xA5, 0xBE, 0x9B, 0x59, 0x35, 0x79, 
-0x83, 0x6E, 0x90, 0x41, 0x9F, 0xF9, 0x3C, 0xB7, 0x6F, 0xDE, 0x67, 0x62, 0xBC, 0x9D, 0x8F, 0x33, 
-0x7F, 0x95, 0xB9, 0xBB, 0xAE, 0x21, 0x5A, 0xE3, 0x00, 0x60, 0xC8, 0xB1, 0xBC, 0xFD, 0x01, 0x84, 
-0x9B, 0xD2, 0x69, 0xED, 0x91, 0x53, 0xC8, 0x5C, 0x39, 0xA0, 0xDC, 0xCF, 0xFC, 0x55, 0xF7, 0x44, 
-0x3E, 0x76, 0x99, 0x03, 0x36, 0x16, 0x00, 0x4F, 0xCC, 0xBD, 0x07, 0xC4, 0xFC, 0x06, 0x40, 0xF6, 
-0x1D, 0x13, 0x19, 0x8B, 0x4B, 0x7A, 0x12, 0x02, 0xCE, 0xAF, 0x05, 0x9E, 0x0B, 0x0C, 0x28, 0xBA, 
-0x98, 0xF9, 0xBD, 0xDF, 0x2D, 0x93, 0x5E, 0x91, 0xBF, 0xD6, 0x68, 0x00, 0x7C, 0x01, 0x95, 0xAF, 
-0x8E, 0x02, 0x90, 0xBE, 0xC7, 0xCD, 0x2C, 0x3B, 0x5F, 0x26, 0x5B, 0xEE, 0xDF, 0x82, 0xF2, 0x81, 
-0x44, 0x07, 0x46, 0x8A, 0xB5, 0xEF, 0xE4, 0xFA, 0xDE, 0x27, 0x23, 0xA7, 0x64, 0x99, 0x03, 0x36, 
-0x16, 0x00, 0x8F, 0x5C, 0x39, 0x05, 0xDB, 0x9D, 0x4A, 0x93, 0x5D, 0x2C, 0x2D, 0xB1, 0xCC, 0xA5, 
-0x1A, 0xEB, 0xDF, 0xF5, 0x98, 0x2C, 0xEF, 0x44, 0x5D, 0x66, 0x54, 0xFE, 0x84, 0xAA, 0x95, 0x1D, 
-0x5D, 0xFE, 0x8C, 0x84, 0x2E, 0xA3, 0x7A, 0xBB, 0xCA, 0x1F, 0xA1, 0xE8, 0x9B, 0x23, 0xE3, 0x76, 
-0xF9, 0xBC, 0x14, 0xC4, 0x2B, 0x55, 0xFA, 0xFE, 0xD8, 0x61, 0x1B, 0x8B, 0x03, 0x6A, 0xB6, 0xEC, 
-0xC6, 0xF9, 0x50, 0x63, 0x01, 0xB0, 0x7C, 0xCE, 0x59, 0x08, 0x1F, 0x0B, 0xE5, 0x96, 0x2E, 0x87, 
-0x86, 0xA6, 0xDA, 0x65, 0x48, 0x9F, 0xE7, 0xC6, 0xA7, 0x7F, 0x5F, 0xCE, 0xEB, 0xD5, 0x78, 0xA7, 
-0xC1, 0x00, 0x68, 0xBF, 0x69, 0xE4, 0xCA, 0x00, 0x73, 0xD1, 0x53, 0x41, 0x2B, 0x28, 0x97, 0x08, 
-0xE9, 0x05, 0x84, 0x93, 0x29, 0x3A, 0x80, 0xA7, 0x5F, 0xE0, 0x33, 0xAB, 0x9F, 0xAE, 0x06, 0x31, 
-0xCB, 0x19, 0xB3, 0xB1, 0x00, 0x78, 0xA2, 0xFD, 0x8B, 0xA8, 0xDE, 0x0F, 0xD2, 0x5C, 0xCE, 0x62, 
-0x02, 0xDF, 0x31, 0x59, 0xCF, 0x2A, 0x37, 0x30, 0xFF, 0xA9, 0x9F, 0x04, 0xF6, 0xAD, 0x51, 0x87, 
-0xC6, 0x02, 0x60, 0x79, 0xFB, 0x2D, 0xA0, 0xDF, 0x89, 0x12, 0x80, 0xAC, 0x23, 0xC1, 0x38, 0x00, 
-0x01, 0xDB, 0x2A, 0x17, 0x80, 0xA0, 0x03, 0x57, 0xA9, 0xBB, 0xD4, 0xFC, 0x82, 0x92, 0x8C, 0x73, 
-0x40, 0x61, 0xB2, 0x3D, 0xD9, 0x7E, 0x0B, 0x5E, 0x06, 0x07, 0x44, 0x0D, 0xC0, 0x38, 0x07, 0x54, 
-0xCE, 0x01, 0x15, 0x61, 0xE2, 0x57, 0xBE, 0xE8, 0x02, 0xAE, 0xEB, 0x5D, 0x51, 0x2A, 0xF3, 0x54, 
-0xAB, 0x7F, 0x63, 0xE9, 0x80, 0xA5, 0xED, 0xD7, 0x60, 0xE9, 0xA3, 0x11, 0xFE, 0xD0, 0x43, 0x2E, 
-0xDD, 0xFA, 0xB0, 0xB5, 0x9D, 0x6B, 0x7B, 0xCD, 0xA5, 0xB2, 0x0D, 0xD1, 0x1A, 0x0B, 0x80, 0xE5, 
-0x73, 0x4D, 0xF5, 0x8C, 0x89, 0x0D, 0x9B, 0x3A, 0xB2, 0x53, 0x7C, 0x73, 0x34, 0xCC, 0x96, 0xCF, 
-0xB9, 0x93, 0x3A, 0x47, 0xF1, 0x1A, 0x0B, 0xD5, 0x5C, 0xB6, 0xFA, 0xBF, 0x28, 0x2F, 0xD2, 0x6C, 
-0xDD, 0xC5, 0xBC, 0x95, 0xEF, 0x36, 0x04, 0xF5, 0xAB, 0x56, 0xA8, 0x5D, 0xEE, 0xEA, 0x4C, 0xFD, 
-0xC0, 0xE9, 0x9B, 0xCD, 0x75, 0xC7, 0xC7, 0x22, 0xF6, 0x23, 0xA8, 0x9A, 0xBB, 0x26, 0x82, 0x7E, 
-0xD6, 0x30, 0xE8, 0x6B, 0x2E, 0xE8, 0x7F, 0x61, 0xB9, 0x37, 0xE3, 0x59, 0xBB, 0x6B, 0x51, 0xF7, 
-0x15, 0x34, 0xA1, 0xCC, 0xE7, 0x8D, 0xC5, 0x01, 0xE9, 0x99, 0x99, 0x9A, 0xB2, 0x89, 0x7F, 0xF8, 
-0x47, 0xD0, 0x2F, 0x09, 0xD2, 0x1C, 0xEE, 0x90, 0x55, 0x60, 0xD9, 0x62, 0x7E, 0x2D, 0xCF, 0xFB, 
-0x26, 0xDB, 0xFA, 0xBE, 0x51, 0x8D, 0xEB, 0xE7, 0x4B, 0x21, 0x76, 0xBE, 0xBE, 0x8D, 0x09, 0x80, 
-0x99, 0xE9, 0xD2, 0xF6, 0xB3, 0xB1, 0x78, 0x2E, 0x55, 0xD4, 0x97, 0x75, 0xE1, 0x87, 0xBF, 0x90, 
-0x7C, 0xA2, 0x29, 0xFD, 0xB7, 0xD1, 0x67, 0xFE, 0x7D, 0xE8, 0xBB, 0xB0, 0x9C, 0xCB, 0xB8, 0x6E, 
-0xCD, 0xAF, 0x2B, 0x25, 0x56, 0x35, 0xDE, 0x6F, 0x5C, 0x00, 0x4C, 0x51, 0xDF, 0x44, 0xEB, 0x4E, 
-0x94, 0xAF, 0xA4, 0x7E, 0x61, 0x75, 0x0C, 0xD1, 0x03, 0xDD, 0x10, 0xFE, 0xAF, 0x21, 0xE9, 0x77, 
-0x68, 0xD3, 0x6F, 0x32, 0x27, 0x75, 0xB5, 0x4D, 0x35, 0xA8, 0x58, 0xC1, 0x98, 0x8D, 0x0B, 0x80, 
-0xCF, 0x05, 0xF3, 0x4E, 0xC2, 0x76, 0x1F, 0xF0, 0xB3, 0xE0, 0x32, 0x15, 0x72, 0x21, 0xC5, 0x9C, 
-0xFD, 0xF7, 0x21, 0x30, 0x77, 0x47, 0x7B, 0x37, 0xD1, 0xD9, 0x38, 0xCE, 0xB7, 0x5C, 0xAC, 0x1A, 
-0x1B, 0x00, 0xBF, 0xA8, 0xEF, 0xE5, 0x19, 0xB8, 0x18, 0xFF, 0xD0, 0x27, 0x51, 0x8C, 0x8F, 0xE8, 
-0xC8, 0x9C, 0xF3, 0x8B, 0x21, 0x93, 0xFB, 0x69, 0x92, 0xAE, 0x7E, 0x46, 0x8C, 0xBF, 0x63, 0xEB, 
-0x79, 0xAF, 0xD5, 0xAB, 0xF8, 0x22, 0x0C, 0x63, 0x34, 0x36, 0x00, 0x66, 0x05, 0x3E, 0x08, 0x9B, 
-0x3F, 0x80, 0x63, 0x2D, 0x1C, 0xB9, 0x3A, 0xEC, 0xD6, 0x11, 0x33, 0xB5, 0xAD, 0xC0, 0x0D, 0x2A, 
-0x26, 0x54, 0x6C, 0x12, 0x5A, 0x0E, 0xA3, 0x3C, 0x86, 0x65, 0xFD, 0x00, 0x2B, 0xF6, 0x46, 0xAD, 
-0x8B, 0xEE, 0xC2, 0x10, 0xBD, 0xF1, 0xAD, 0xA0, 0x7C, 0xAB, 0x58, 0x35, 0x77, 0x22, 0x7D, 0x9C, 
-0x83, 0xC5, 0x55, 0x88, 0x5C, 0xED, 0x5F, 0x83, 0x73, 0xC4, 0x44, 0x35, 0x37, 0x9B, 0xEC, 0x45, 
-0x59, 0x8D, 0xB2, 0x12, 0x9C, 0xCD, 0xCC, 0x5F, 0xB3, 0xAF, 0x9E, 0x85, 0x17, 0x61, 0x81, 0x68, 
-0x7C, 0x0E, 0xC8, 0x5C, 0x49, 0xFA, 0x8A, 0x9B, 0x56, 0xE7, 0x28, 0xEC, 0xA6, 0x0F, 0xE2, 0xE9, 
-0x71, 0xA8, 0x28, 0x71, 0xDD, 0x49, 0x2C, 0xF6, 0x3B, 0x0E, 0x1D, 0xDC, 0xCB, 0x82, 0x75, 0xE6, 
-0xA2, 0x8D, 0x8A, 0x2C, 0xD7, 0xB0, 0xC4, 0x8B, 0xA2, 0xDF, 0x7B, 0x0B, 0x80, 0x28, 0x56, 0xDC, 
-0x60, 0x63, 0x8C, 0x03, 0x50, 0x67, 0x40, 0xC6, 0x01, 0x18, 0x07, 0xA0, 0xCE, 0x14, 0xA8, 0xF3, 
-0xE7, 0xFF, 0x0F, 0xB7, 0x80, 0x16, 0xCA, 0xD9, 0x27, 0x5C, 0xC7, 0x00, 0x00, 0x00, 0x00, 0x49, 
-0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82
-};
\ No newline at end of file
diff --git a/src/www/setupPage.html b/src/www/setupPage.html
index 64a531b..9e1273f 100644
--- a/src/www/setupPage.html
+++ b/src/www/setupPage.html
@@ -5,439 +5,556 @@
     
     
     BLLED Setup
-    
+    
 
 
 
     
     
-

Configuration

-

Use the options below to configure your BLLED Controller.

- - - - -
- LED Behaviour -
-
- - Maintenance Mode (Always On) -
- + + WiFi-Signal + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+ LED Behaviour +
+ +
+
+ + Maintenance Mode (Always On) +
+ +
+ + RGB Color Cycle Mode (Always On) +
+ +
+ + Replicate State +
+ + + + + +
+
+ +
+ + Color Test (Always On) +
+ + + + + +
+
+ +
+ + Show Wifi Strength via LEDs +
+ +
LED Actions
+ +
+ + Finish Indication + +
+ + + + + +
+
+ + + +
+ + Inactivity Timeout (Minutes) +
+ + +
+
- -
- - Replicate LED State - - -
- - WW - CW +
+ +
+ Printer Dependant +
+
+ +
+ + Connecting to a P1 Printer? +
+ +
+ + Stages with Lidar in use (if installed) +
+ +
LED Actions
+ +
+ Cleaning Nozzle +
+ + + + + +
+
+ +
+ Bed Leveling +
+ + + + + +
+
+ +
+ Calibrating Extrusion +
+ + + + + +
+
+ +
+ Scanning Bed Surface +
+ + + + + +
+
+ +
+ First Layer Inspection +
+ + + + + +
- -
- - +
+ Error Detection / Colors +
+ +
+ + +
+ + Error Detection +
+
+
+ WiFi Setup / Scanning +
+ + + + +
-
--> - - -
- - Replicate LED State -
-
-
- - - - - - - - - - - -
- LED Color -
- - -
-
- -
- MQTT Settings -
- - -
-
- -
- Navigation -
- - - -
-
- - +
+
+ Filament Runout +
+ + + + + +
+
+
+ Front Cover Removed +
+ + + + + +
+
+
+ Nozzle Temp Fail +
+ + + + + +
+
+
+ Bed Temp Fail +
+ + + + + +
+
+
+ + + +
+ Debug Options +
+
+ +
+ + Debugging +
+ +
+ + Debugging OnChange Events +
+ +
+ + MQTT Logging +
+
+
+ +
+ Navigation +
+
+ + + + +
+
+ + +

Firmware version: ??.??.??

ℹ️Placeholder
+ + + + + - document.querySelectorAll("details.collapse").forEach((detail) => { - detail.addEventListener("toggle", function () { - if (detail.open) { - document.querySelectorAll("details.collapse").forEach((other) => { - if (other !== detail) other.removeAttribute("open"); - }); + + + diff --git a/src/www/setupPageOld.html b/src/www/setupPageOld.html index 031c72f..9031f9b 100644 --- a/src/www/setupPageOld.html +++ b/src/www/setupPageOld.html @@ -3,8 +3,8 @@ - - + + BLLED Setup + @@ -147,12 +13,11 @@
-

This page allows you to update your device firmware over the air.

@@ -228,19 +93,43 @@

BLLED OTA Update

function completeHandler(event) { _("progressBar").value = 0; - alertToast("success", "Update complete!"); + _('status').textContent = "Upload complete. Rebooting..."; + alertToast("success", "Firmware uploaded successfully!"); + + let attempts = 0; + let maxAttempts = 30; + const interval = setInterval(() => { + fetch("/") + .then(response => { + if (response.ok) { + clearInterval(interval); + alertToast("success", "Device is back online!"); + location.href = "/"; + } + }) + .catch(() => { + attempts++; + if (attempts >= maxAttempts) { + clearInterval(interval); + alertToast("error", "Device did not come back online."); + } + }); + }, 2000); } function startHandler(event) { - alertToast("info", "Uploading..."); + _('status').textContent = "Uploading..."; + alertToast("info", "Uploading firmware..."); } function errorHandler(event) { - alertToast("error", "Error during update."); + _('status').textContent = "Upload failed."; + alertToast("error", "Firmware upload failed!"); } function abortHandler(event) { - alertToast("warning", "Update aborted."); + _('status').textContent = "Upload aborted."; + alertToast("warning", "Firmware upload aborted."); } @@ -255,6 +144,7 @@

BLLED OTA Update

_('status').textContent = "Firmware Upload!"; }); +
ℹ️Placeholder
\ No newline at end of file diff --git a/src/www/webSerialPage.html b/src/www/webSerialPage.html new file mode 100644 index 0000000..8292f92 --- /dev/null +++ b/src/www/webSerialPage.html @@ -0,0 +1,394 @@ + + + + + + + Web Console + + + + + + +
+ + +
+
+ + + +
+ + +
+

+

+ + + + + \ No newline at end of file diff --git a/src/www/wifiSetup.html b/src/www/wifiSetup.html index b579ff1..a304d31 100644 --- a/src/www/wifiSetup.html +++ b/src/www/wifiSetup.html @@ -5,157 +5,14 @@ BLLED WiFi Setup - +
diff --git a/test/printerjsonexample.json b/test/printerjsonexample.json new file mode 100644 index 0000000..7390adb --- /dev/null +++ b/test/printerjsonexample.json @@ -0,0 +1,774 @@ +{ + "2D": { + "bs": { + "bi": [ + { + "clock_in": false, + "est_time": 0, + "idx": 0, + "print_then": false, + "proc_list": [], + "step_type": 1, + "tool_info": { + "color": "", + "diameter": 0.4000000059604645, + "id": 8978432 + }, + "type": 137 + } + ], + "total_time": 0 + }, + "cond": 14, + "cur_stage": { + "clock_in_time": 0, + "idx": 0, + "left_time": 0, + "process": 0, + "state": 0 + }, + "first_confirm": false, + "makeable": false, + "material": { + "cur_id_list": [], + "state": 0, + "tar_id": "", + "tar_name": "" + } + }, + "3D": { + "layer_num": 1, + "total_layer_num": 435 + }, + "ams": { + "ams": [ + { + "dry_time": 0, + "humidity": "4", + "humidity_raw": "25", + "id": "0", + "info": "1003", + "temp": "27.5", + "tray": [ + { + "bed_temp": "0", + "bed_temp_type": "0", + "cali_idx": -1, + "cols": [ + "000000FF" + ], + "ctype": 0, + "drying_temp": "80", + "drying_time": "8", + "id": "0", + "nozzle_temp_max": "270", + "nozzle_temp_min": "240", + "remain": 100, + "state": 11, + "tag_uid": "CAD4127600000100", + "total_len": 330000, + "tray_color": "000000FF", + "tray_diameter": "1.75", + "tray_id_name": "B00-K0", + "tray_info_idx": "GFB00", + "tray_sub_brands": "ABS", + "tray_type": "ABS", + "tray_uuid": "4CD95CB1ABC44B0EA1EDA631CB0595A8", + "tray_weight": "1000", + "xcam_info": "803E1027E803E8033333333F" + }, + { + "bed_temp": "0", + "bed_temp_type": "0", + "cali_idx": -1, + "cols": [ + "000000FF" + ], + "ctype": 0, + "drying_temp": "80", + "drying_time": "8", + "id": "1", + "nozzle_temp_max": "270", + "nozzle_temp_min": "240", + "remain": 100, + "state": 11, + "tag_uid": "FA261DF400000100", + "total_len": 330000, + "tray_color": "000000FF", + "tray_diameter": "1.75", + "tray_id_name": "B00-K0", + "tray_info_idx": "GFB00", + "tray_sub_brands": "ABS", + "tray_type": "ABS", + "tray_uuid": "8A892CB7DF894F68A08C0A8E28DCFDF1", + "tray_weight": "1000", + "xcam_info": "803E1027E803E8033333333F" + }, + { + "bed_temp": "70", + "bed_temp_type": "2", + "cali_idx": -1, + "cols": [ + "F2EADAFF" + ], + "ctype": 0, + "drying_temp": "65", + "drying_time": "8", + "id": "2", + "nozzle_temp_max": "270", + "nozzle_temp_min": "220", + "remain": 100, + "state": 11, + "tag_uid": "324BBF7400000100", + "total_len": 330000, + "tray_color": "F2EADAFF", + "tray_diameter": "1.75", + "tray_id_name": "G00-W4", + "tray_info_idx": "GFG00", + "tray_sub_brands": "PETG Basic", + "tray_type": "PETG", + "tray_uuid": "E3604E1558A54D2B8F65FB017E85D649", + "tray_weight": "1000", + "xcam_info": "8813D007E803E8039A99193F" + }, + { + "bed_temp": "80", + "bed_temp_type": "1", + "cali_idx": -1, + "cols": [ + "000000FF" + ], + "ctype": 0, + "drying_temp": "80", + "drying_time": "8", + "id": "3", + "nozzle_temp_max": "270", + "nozzle_temp_min": "240", + "remain": 53, + "state": 11, + "tag_uid": "60347D2F00000100", + "total_len": 330000, + "tray_color": "000000FF", + "tray_diameter": "1.75", + "tray_id_name": "B01-K0", + "tray_info_idx": "GFB01", + "tray_sub_brands": "ASA", + "tray_type": "ASA", + "tray_uuid": "E746641127C74A8A8276FB4A6A1D9B97", + "tray_weight": "1000", + "xcam_info": "803E1027E803E8030000803F" + } + ] + }, + { + "dry_time": 0, + "humidity": "4", + "humidity_raw": "25", + "id": "1", + "info": "1103", + "temp": "27.7", + "tray": [ + { + "bed_temp": "90", + "bed_temp_type": "2", + "cali_idx": -1, + "cols": [ + "FFFFFFFF" + ], + "ctype": 0, + "drying_temp": "80", + "drying_time": "8", + "id": "0", + "nozzle_temp_max": "270", + "nozzle_temp_min": "240", + "remain": 60, + "state": 11, + "tag_uid": "70F7792E00000100", + "total_len": 330000, + "tray_color": "FFFFFFFF", + "tray_diameter": "1.75", + "tray_id_name": "B00-W0", + "tray_info_idx": "GFB00", + "tray_sub_brands": "ABS", + "tray_type": "ABS", + "tray_uuid": "DE09C5C1E84A41F8981AA97FC30187CE", + "tray_weight": "1000", + "xcam_info": "D007D007E803E803CDCC4C3F" + }, + { + "bed_temp": "35", + "bed_temp_type": "1", + "cali_idx": -1, + "cols": [ + "000000FF" + ], + "ctype": 0, + "drying_temp": "55", + "drying_time": "8", + "id": "1", + "nozzle_temp_max": "230", + "nozzle_temp_min": "190", + "remain": 100, + "state": 11, + "tag_uid": "6CE9285500000100", + "total_len": 330000, + "tray_color": "000000FF", + "tray_diameter": "1.75", + "tray_id_name": "A00-K0", + "tray_info_idx": "GFA00", + "tray_sub_brands": "PLA Basic", + "tray_type": "PLA", + "tray_uuid": "F849A72301624376B132C2FF96A5C498", + "tray_weight": "1000", + "xcam_info": "803E803EE803E803CDCC4C3F" + }, + { + "bed_temp": "35", + "bed_temp_type": "1", + "cali_idx": -1, + "cols": [ + "F17B8FFF" + ], + "ctype": 0, + "drying_temp": "55", + "drying_time": "8", + "id": "2", + "nozzle_temp_max": "230", + "nozzle_temp_min": "190", + "remain": 100, + "state": 11, + "tag_uid": "BC2C04D000000100", + "total_len": 330000, + "tray_color": "F17B8FFF", + "tray_diameter": "1.75", + "tray_id_name": "A12-R0", + "tray_info_idx": "GFA12", + "tray_sub_brands": "PLA Glow", + "tray_type": "PLA", + "tray_uuid": "DEF3509E89094379A419EADEF3BE9F45", + "tray_weight": "1000", + "xcam_info": "AC0DD0078403E8033333333F" + }, + { + "bed_temp": "35", + "bed_temp_type": "1", + "cali_idx": -1, + "cols": [ + "A1FFACFF" + ], + "ctype": 0, + "drying_temp": "55", + "drying_time": "8", + "id": "3", + "nozzle_temp_max": "230", + "nozzle_temp_min": "190", + "remain": 100, + "state": 11, + "tag_uid": "AA0A93AA00000100", + "total_len": 330000, + "tray_color": "A1FFACFF", + "tray_diameter": "1.75", + "tray_id_name": "A12-G0", + "tray_info_idx": "GFA12", + "tray_sub_brands": "PLA Glow", + "tray_type": "PLA", + "tray_uuid": "17A15669F8524BAEA8A0F5CA89E609D2", + "tray_weight": "1000", + "xcam_info": "881388138403E8033333333F" + } + ] + } + ], + "ams_exist_bits": "3", + "ams_exist_bits_raw": "3", + "cali_id": 255, + "cali_stat": 0, + "insert_flag": true, + "power_on_flag": false, + "tray_exist_bits": "ff", + "tray_is_bbl_bits": "ff", + "tray_now": "1", + "tray_pre": "1", + "tray_read_done_bits": "ff", + "tray_reading_bits": "0", + "tray_tar": "1", + "unbind_ams_stat": 0, + "version": 69132 + }, + "ams_rfid_status": 0, + "ams_status": 768, + "ap_err": 0, + "aux": "2001004", + "aux_part_fan": false, + "batch_id": 0, + "bed_target_temper": 55, + "bed_temper": 55, + "big_fan1_speed": "0", + "big_fan2_speed": "4", + "cali_version": 0, + "canvas_id": 0, + "care": [ + { + "id": "lr", + "info": "1864" + }, + { + "id": "fa", + "info": "1864" + }, + { + "id": "ls", + "info": "1864" + }, + { + "id": "cr", + "info": "1864" + }, + { + "id": "ld", + "info": "1864" + } + ], + "cfg": "385FDAD9", + "chamber_temper": 32, + "command": "push_status", + "cooling_fan_speed": "0", + "ctt": 0, + "design_id": "", + "device": { + "airduct": { + "modeCur": 0, + "modeList": [ + { + "ctrl": [ + 16, + 32, + 48 + ], + "modeId": 0, + "off": [ + 96 + ] + }, + { + "ctrl": [ + 16 + ], + "modeId": 1, + "off": [ + 32, + 48 + ] + }, + { + "ctrl": [ + 48 + ], + "modeId": 2, + "off": [] + } + ], + "parts": [ + { + "func": 0, + "id": 16, + "range": 6553600, + "state": 0 + }, + { + "func": 1, + "id": 32, + "range": 6553600, + "state": 0 + }, + { + "func": 2, + "id": 48, + "range": 6553600, + "state": 30 + }, + { + "func": 3, + "id": 96, + "range": 6553600, + "state": 0 + } + ] + }, + "bed": { + "info": { + "temp": 3604535 + }, + "state": 2 + }, + "bed_temp": 3604535, + "cam": { + "laser": { + "cond": 252, + "state": 0 + } + }, + "cham_temp": 32, + "ctc": { + "info": { + "temp": 31 + }, + "state": 0 + }, + "ext_tool": { + "calib": 2, + "low_prec": true, + "mount": 0, + "th_temp": 0, + "type": "" + }, + "extruder": { + "info": [ + { + "filam_bak": [ + 3 + ], + "hnow": 0, + "hpre": 0, + "htar": 0, + "id": 0, + "info": 9, + "snow": 65535, + "spre": 65535, + "star": 65535, + "stat": 0, + "temp": 44 + }, + { + "filam_bak": [], + "hnow": 1, + "hpre": 1, + "htar": 1, + "id": 1, + "info": 94, + "snow": 257, + "spre": 257, + "star": 257, + "stat": 197376, + "temp": 14418140 + } + ], + "state": 33042 + }, + "fan": 410080, + "laser": { + "power": 0 + }, + "nozzle": { + "exist": 3, + "info": [ + { + "diameter": 0.4, + "id": 0, + "tm": 0, + "type": "HS01", + "wear": 0 + }, + { + "diameter": 0.4, + "id": 1, + "tm": 0, + "type": "HS01", + "wear": 0 + } + ], + "state": 0 + }, + "plate": { + "base": 4, + "cali2d_id": "", + "cur_id": "P0101", + "mat": 1, + "tar_id": "" + }, + "type": 1 + }, + "err": "0", + "fail_reason": "0", + "fan_gear": 4980736, + "file": "/data/Metadata/plate_1.gcode", + "force_upgrade": false, + "fun": "41AFFF9CFF", + "gcode_file": "/data/Metadata/plate_1.gcode", + "gcode_file_prepare_percent": "100", + "gcode_state": "RUNNING", + "heatbreak_fan_speed": "15", + "hms": [], + "home_flag": -1066934785, + "hw_switch_state": 2, + "ipcam": { + "agora_service": "disable", + "brtc_service": "enable", + "bs_state": 0, + "ipcam_dev": "1", + "ipcam_record": "enable", + "laser_preview_res": 5, + "mode_bits": 2, + "resolution": "1080p", + "rtsp_url": "disable", + "timelapse": "disable", + "tl_store_hpd_type": 2, + "tl_store_path_type": 2, + "tutk_server": "enable" + }, + "job": { + "cur_stage": { + "idx": 0, + "state": 2 + }, + "stage": [ + { + "clock_in": false, + "color": [ + "", + "" + ], + "diameter": [ + 0.4000000059604645, + 0.4000000059604645 + ], + "est_time": 0, + "heigh": 0, + "idx": 0, + "platform": "", + "print_then": false, + "proc_list": [], + "tool": [ + "HS01", + "HS01" + ], + "type": 2 + } + ] + }, + "job_attr": 17, + "job_id": "352511791", + "lan_task_id": "0", + "layer_num": 1, + "lights_report": [ + { + "mode": "on", + "node": "chamber_light" + }, + { + "mode": "flashing", + "node": "work_light" + }, + { + "mode": "on", + "node": "chamber_light2" + } + ], + "maintain": 3, + "mapping": [ + 65535, + 65535, + 65535, + 65535, + 65535, + 65535, + 65535, + 257 + ], + "mc_action": 0, + "mc_err": 0, + "mc_percent": 8, + "mc_print_error_code": "0", + "mc_print_stage": "2", + "mc_print_sub_stage": 0, + "mc_remaining_time": 313, + "mc_stage": 2, + "model_id": "US4932babe82ce32", + "net": { + "conf": 16, + "info": [ + { + "ip": 2713495744, + "mask": 16777215 + }, + { + "ip": 0, + "mask": 0 + } + ] + }, + "nozzle_diameter": "0.4", + "nozzle_target_temper": 0, + "nozzle_temper": 44, + "nozzle_type": "stainless_steel", + "online": { + "ahb": true, + "ext": true, + "version": 8 + }, + "percent": 8, + "plate_cnt": 2, + "plate_id": 1, + "plate_idx": 1, + "prepare_per": 100, + "print_error": 0, + "print_gcode_action": 0, + "print_real_action": 0, + "print_type": "cloud", + "profile_id": "305233194", + "project_id": "331855685", + "queue": 0, + "queue_est": 0, + "queue_number": 0, + "queue_sts": 0, + "queue_total": 0, + "remain_time": 313, + "s_obj": [], + "sdcard": true, + "sequence_id": "2021", + "spd_lvl": 2, + "spd_mag": 100, + "stat": "16382081F0", + "state": 4, + "stg": [ + 29, + 13, + 4, + 8, + 14, + 1, + 3, + 39 + ], + "stg_cur": 0, + "subtask_id": "675488755", + "subtask_name": "QBRICK-Akkufach v3-SOLID-1", + "task_id": "675488754", + "total_layer_num": 435, + "upgrade_state": { + "ahb_new_version_number": "", + "ams_new_version_number": "", + "consistency_request": false, + "dis_state": 0, + "err_code": 0, + "ext_new_version_number": "", + "force_upgrade": false, + "idx": 8, + "idx2": 1579120524, + "lower_limit": "00.00.00.00", + "message": "", + "module": "", + "new_version_state": 1, + "ota_new_version_number": "01.01.02.04", + "progress": "0", + "sequence_id": 0, + "sn": "0948BB510200105", + "status": "IDLE" + }, + "upload": { + "file_size": 0, + "finish_size": 0, + "message": "Good", + "oss_url": "", + "progress": 0, + "sequence_id": "0903", + "speed": 0, + "status": "idle", + "task_id": "", + "time_remaining": 0, + "trouble_id": "" + }, + "ver": "20000", + "vir_slot": [ + { + "bed_temp": "0", + "bed_temp_type": "0", + "cali_idx": -1, + "cols": [ + "FFFFFF00" + ], + "ctype": 0, + "drying_temp": "0", + "drying_time": "0", + "id": "254", + "nozzle_temp_max": "0", + "nozzle_temp_min": "0", + "remain": 0, + "tag_uid": "0000000000000000", + "total_len": 330000, + "tray_color": "FFFFFF00", + "tray_diameter": "1.75", + "tray_id_name": "", + "tray_info_idx": "", + "tray_sub_brands": "", + "tray_type": "", + "tray_uuid": "00000000000000000000000000000000", + "tray_weight": "0", + "xcam_info": "000000000000000000000000" + }, + { + "bed_temp": "0", + "bed_temp_type": "0", + "cali_idx": -1, + "cols": [ + "00000000" + ], + "ctype": 0, + "drying_temp": "0", + "drying_time": "0", + "id": "255", + "nozzle_temp_max": "0", + "nozzle_temp_min": "0", + "remain": 0, + "tag_uid": "0000000000000000", + "total_len": 330000, + "tray_color": "00000000", + "tray_diameter": "1.75", + "tray_id_name": "", + "tray_info_idx": "", + "tray_sub_brands": "", + "tray_type": "", + "tray_uuid": "00000000000000000000000000000000", + "tray_weight": "0", + "xcam_info": "000000000000000000000000" + } + ], + "vt_tray": { + "bed_temp": "0", + "bed_temp_type": "0", + "cali_idx": -1, + "cols": [ + "00000000" + ], + "ctype": 0, + "drying_temp": "0", + "drying_time": "0", + "id": "255", + "nozzle_temp_max": "0", + "nozzle_temp_min": "0", + "remain": 0, + "tag_uid": "0000000000000000", + "total_len": 330000, + "tray_color": "00000000", + "tray_diameter": "1.75", + "tray_id_name": "", + "tray_info_idx": "", + "tray_sub_brands": "", + "tray_type": "", + "tray_uuid": "00000000000000000000000000000000", + "tray_weight": "0", + "xcam_info": "000000000000000000000000" + }, + "wifi_signal": "-68dBm", + "xcam": { + "allow_skip_parts": false, + "buildplate_marker_detector": true, + "cfg": 224695, + "first_layer_inspector": true, + "halt_print_sensitivity": "medium", + "print_halt": true, + "printing_monitor": true, + "spaghetti_detector": true + }, + "xcam_status": "0" +} \ No newline at end of file