From da41b931402a0ab9ab7fcc046fbd6547e1c7b7a5 Mon Sep 17 00:00:00 2001 From: Jeka Der Date: Tue, 24 Oct 2023 00:56:31 +0200 Subject: [PATCH 01/13] add large non-bold clock font --- src/PixelIt.ino | 42 ++++++++++++++++++++++++++++++-------- src/PixelItFont.h | 51 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 8 deletions(-) diff --git a/src/PixelIt.ino b/src/PixelIt.ino index aec8037..6b39af8 100644 --- a/src/PixelIt.ino +++ b/src/PixelIt.ino @@ -293,6 +293,8 @@ uint8_t clockColorR = 255, clockColorG = 255, clockColorB = 255; uint clockAutoFallbackTime = 30; bool forceClock = false; bool clockBlinkAnimated = true; +uint clockFontChoise = 2; +bool clockLargeFont = false; bool clockFatFont = false; bool clockDrawWeekDays = true; @@ -517,6 +519,7 @@ void SaveConfig() json["clockDateDayMonth"] = clockDateDayMonth; json["clockDayOfWeekFirstMonday"] = clockDayOfWeekFirstMonday; json["clockBlinkAnimated"] = clockBlinkAnimated; + json["clockLargeFont"] = clockLargeFont; json["clockFatFont"] = clockFatFont; json["clockDrawWeekDays"] = clockDrawWeekDays; json["scrollTextDefaultDelay"] = scrollTextDefaultDelay; @@ -746,11 +749,15 @@ void SetConfigVariables(JsonObject &json) clockDayOfWeekFirstMonday = json["clockDayOfWeekFirstMonday"].as(); } + if (json.containsKey("clockLargeFont")) + { + clockLargeFont = json["clockLargeFont"].as(); + } + if (json.containsKey("clockFatFont")) { clockFatFont = json["clockFatFont"].as(); } - if (json.containsKey("clockDrawWeekDays")) { clockDrawWeekDays = json["clockDrawWeekDays"].as(); @@ -1559,7 +1566,12 @@ void CreateFrames(JsonObject &json, int forceDuration) logMessage += F("fatFont, "); clockFatFont = json["clock"]["fatFont"]; } - + bool isLargeFontSet = json["clock"]["largeFont"].is(); + if (isLargeFontSet) + { + logMessage += F("largeFont, "); + clockLargeFont = json["clock"]["largeFont"]; + } bool isDrawWeekDaysSet = json["clock"]["drawWeekDays"].is(); if (isDrawWeekDaysSet) { @@ -2169,9 +2181,9 @@ void DrawTextHelper(String text, int bigFont, bool centerText, bool scrollText, // Position correction posY = posY - 1; } - else if (bigFont == 2) // very large font, only to be used for time display / very large font, only for the time display + else if (bigFont == 2) // fat font, only to be used for time display { - // Set very large font + // Set fat font matrix->setFont(&FatPixels); matrix->getTextBounds(text, 0, 0, &boundsx1, &boundsy1, &boundsw, &boundsh); @@ -2180,6 +2192,17 @@ void DrawTextHelper(String text, int bigFont, bool centerText, bool scrollText, // Position correction posY = posY + 6; } + else if (bigFont == 3) // very large font, only to be used for time display + { + // Set very large font + matrix->setFont(&LargePixels); + + matrix->getTextBounds(text, 0, 0, &boundsx1, &boundsy1, &boundsw, &boundsh); + xTextWidth = boundsw; + + // Position correction + posY = posY + 6; + } else { // Set small font @@ -2457,17 +2480,20 @@ void DrawClock(bool fromJSON) { clockCounterClock++; } - + if (clockLargeFont) // use non-bold font + { + clockFontChoise = 3; + } if (clockCounterClock > clockSwitchSec) { clockCounterDate = 0; if (clockFatFont) // fade rather than vertical animate purely because DrawTextCenter doesnt have a Y argument... { - DrawTextCenter(String(time), 2, clockColorR, clockColorG, clockColorB, 0, 1); + DrawTextCenter(String(time), clockFontChoise, clockColorR, clockColorG, clockColorB, 0, 1); FadeOut(30); matrix->clear(); - DrawTextCenter(String(date), 2, clockColorR, clockColorG, clockColorB, 0, 1); + DrawTextCenter(String(date), clockFontChoise, clockColorR, clockColorG, clockColorB, 0, 1); FadeIn(30); } else @@ -2492,7 +2518,7 @@ void DrawClock(bool fromJSON) else if (clockFatFont) { - DrawTextCenter(String(time), 2, clockColorR, clockColorG, clockColorB, 0, 1); + DrawTextCenter(String(time), clockFontChoise, clockColorR, clockColorG, clockColorB, 0, 1); } else { diff --git a/src/PixelItFont.h b/src/PixelItFont.h index 8ff183d..bc83d0a 100644 --- a/src/PixelItFont.h +++ b/src/PixelItFont.h @@ -476,6 +476,57 @@ const GFXglyph PixelItGlyphs[] PROGMEM = { const GFXfont PixelItFont PROGMEM = {(uint8_t *)PixelItBitmaps, (GFXglyph *)PixelItGlyphs, 0x20, 0xE9, 6}; +const uint8_t LargePixels_Bitmaps[] PROGMEM = { + // ASCII code and symbol + 0x00, // 0x20 ' ' + 0x80, // 0x21 '!' + 0x74, 0x63, 0x18, 0xC6, 0x2E, // 0x30 '0' + 0x59, 0x24, 0x97, // 0x31 '1' + 0x74, 0x42, 0x22, 0x22, 0x1F, // 0x32 '2' + 0x74, 0x42, 0x60, 0x86, 0x2E, // 0x33 '3' + 0x19, 0x53, 0x1F, 0x84, 0x21, // 0x34 '4' + 0xFC, 0x21, 0xE0, 0x86, 0x2E, // 0x35 '5' + 0x74, 0x61, 0xE8, 0xC6, 0x2E, // 0x36 '6' + 0xF8, 0x42, 0x22, 0x21, 0x08, // 0x37 '7' + 0x74, 0x62, 0xE8, 0xC6, 0x2E, // 0x38 '8' + 0x74, 0x63, 0x17, 0x86, 0x2E, // 0x39 '9' + 0x90 // 0x3A ':' +}; + +// {offset, width, height, advance cursor, x offset, y offset} +const GFXglyph LargePixels_Glyphs[] PROGMEM = { + // ASCII code and symbol + {0, 1, 1, 2, 0, -5}, // 0x20 ' ' + {0, 0, 0, 0, 0, 0}, // 0x21 '!' + {0, 0, 0, 0, 0, 0}, // 0x22 '"' + {0, 0, 0, 0, 0, 0}, // 0x23 '#' + {0, 0, 0, 0, 0, 0}, // 0x24 '$' + {0, 0, 0, 0, 0, 0}, // 0x25 '%' + {0, 0, 0, 0, 0, 0}, // 0x26 '&' + {0, 0, 0, 0, 0, 0}, // 0x27 ''' + {0, 0, 0, 0, 0, 0}, // 0x28 '(' + {0, 0, 0, 0, 0, 0}, // 0x29 ')' + {0, 0, 0, 0, 0, 0}, // 0x2A '*' + {0, 0, 0, 0, 0, 0}, // 0x2B '+' + {0, 0, 0, 0, 0, 0}, // 0x2C ',' + {0, 0, 0, 0, 0, 0}, // 0x2D '-' + {1, 1, 1, 2, 0, 0}, // 0x2E '.' + {0, 0, 0, 0, 0, 0}, // 0x2F '/' + {2, 5, 8, 6, 0, -7}, // 0x30 '0' + {7, 3, 8, 4, 0, -7}, // 0x31 '1' + {10, 5, 8, 6, 0, -7}, // 0x32 '2' + {15, 5, 8, 6, 0, -7}, // 0x33 '3' + {20, 5, 8, 6, 0, -7}, // 0x34 '4' + {25, 5, 8, 6, 0, -7}, // 0x35 '5' + {30, 5, 8, 6, 0, -7}, // 0x36 '6' + {35, 5, 8, 6, 0, -7}, // 0x37 '7' + {40, 5, 8, 6, 0, -7}, // 0x38 '8' + {45, 5, 8, 6, 0, -7}, // 0x39 '9' + {50, 1, 4, 2, 0, -5} // 0x3A ':' +}; + +const GFXfont LargePixels PROGMEM = {(uint8_t *)LargePixels_Bitmaps, (GFXglyph *)LargePixels_Glyphs, 0x20, 0x3A, 8}; + const uint8_t FatPixels_Bitmaps[] PROGMEM = { // ASCII code and symbol 0x00, // 0x20 ' ' From bef00ffed8289bc7d86c44753ce6295cbe19d5ae Mon Sep 17 00:00:00 2001 From: Jeka Der Date: Tue, 24 Oct 2023 01:26:59 +0200 Subject: [PATCH 02/13] add more conditions for large font rendering --- src/PixelIt.ino | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/PixelIt.ino b/src/PixelIt.ino index 6b39af8..633069b 100644 --- a/src/PixelIt.ino +++ b/src/PixelIt.ino @@ -2424,7 +2424,7 @@ void DrawClock(bool fromJSON) sprintf_P(date, PSTR("%02d/%02d"), month(), day()); } - if (clock24Hours && clockWithSeconds && !clockFatFont) + if (clock24Hours && clockWithSeconds && !clockFatFont && !clockLargeFont) { xPosTime = 2; sprintf_P(time, PSTR("%02d:%02d:%02d"), hour(), minute(), second()); @@ -2436,7 +2436,7 @@ void DrawClock(bool fromJSON) if (clockBlink && clockBlinkAnimated) { clockBlink = false; - if (!clockFatFont) + if (!clockFatFont && !clockLargeFont) { sprintf_P(time, PSTR("%2d %02d %s"), hourFormat12(), minute(), isAM() ? "AM" : "PM"); } @@ -2448,7 +2448,7 @@ void DrawClock(bool fromJSON) else { clockBlink = !clockBlink; - if (!clockFatFont) + if (!clockFatFont && !clockLargeFont) { sprintf_P(time, PSTR("%2d:%02d %s"), hourFormat12(), minute(), isAM() ? "AM" : "PM"); } @@ -2488,7 +2488,7 @@ void DrawClock(bool fromJSON) { clockCounterDate = 0; - if (clockFatFont) // fade rather than vertical animate purely because DrawTextCenter doesnt have a Y argument... + if (clockFatFont || clockLargeFont) // fade rather than vertical animate purely because DrawTextCenter doesnt have a Y argument... { DrawTextCenter(String(time), clockFontChoise, clockColorR, clockColorG, clockColorB, 0, 1); FadeOut(30); @@ -2515,7 +2515,7 @@ void DrawClock(bool fromJSON) } } } - else if (clockFatFont) + else if (clockFatFont || clockLargeFont) { DrawTextCenter(String(time), clockFontChoise, clockColorR, clockColorG, clockColorB, 0, 1); @@ -2534,7 +2534,7 @@ void DrawClock(bool fromJSON) { clockCounterClock = 0; - if (clockFatFont) // fade rather than vertical animate purely because DrawTextCenter doesnt have a Y argument... + if (clockFatFont || clockLargeFont) // fade rather than vertical animate purely because DrawTextCenter doesnt have a Y argument... { DrawTextCenter(String(date), 2, clockColorR, clockColorG, clockColorB, 0, 1); FadeOut(30); @@ -2561,9 +2561,9 @@ void DrawClock(bool fromJSON) } } } - else if (clockFatFont) + else if (clockFatFont || clockLargeFont) { - DrawTextCenter(String(date), 2, clockColorR, clockColorG, clockColorB, 0, 1); + DrawTextCenter(String(date), clockFontChoise, clockColorR, clockColorG, clockColorB, 0, 1); } else { @@ -2571,7 +2571,7 @@ void DrawClock(bool fromJSON) } } - if (!clockFatFont && clockDrawWeekDays) + if (!clockFatFont && !clockLargeFont && clockDrawWeekDays) { DrawWeekDay(); } From d708dd6e1ad55e2ff9d55c50c431285d5758ecc6 Mon Sep 17 00:00:00 2001 From: Jeka Der Date: Sat, 28 Oct 2023 14:48:42 +0200 Subject: [PATCH 03/13] optimize large font logic --- src/PixelIt.ino | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/PixelIt.ino b/src/PixelIt.ino index 633069b..c2c1fcb 100644 --- a/src/PixelIt.ino +++ b/src/PixelIt.ino @@ -2415,6 +2415,13 @@ void DrawClock(bool fromJSON) int xPosTime = 0; + // check if a large font is in use + bool clockFontIsLarge = false; + if (clockLargeFont || clockFatFont) + { + clockFontIsLarge = true; + } + if (clockDateDayMonth) { sprintf_P(date, PSTR("%02d.%02d."), day(), month()); @@ -2424,7 +2431,7 @@ void DrawClock(bool fromJSON) sprintf_P(date, PSTR("%02d/%02d"), month(), day()); } - if (clock24Hours && clockWithSeconds && !clockFatFont && !clockLargeFont) + if (clock24Hours && clockWithSeconds && !clockFontIsLarge) { xPosTime = 2; sprintf_P(time, PSTR("%02d:%02d:%02d"), hour(), minute(), second()); @@ -2436,7 +2443,7 @@ void DrawClock(bool fromJSON) if (clockBlink && clockBlinkAnimated) { clockBlink = false; - if (!clockFatFont && !clockLargeFont) + if (!clockFontIsLarge) { sprintf_P(time, PSTR("%2d %02d %s"), hourFormat12(), minute(), isAM() ? "AM" : "PM"); } @@ -2448,7 +2455,7 @@ void DrawClock(bool fromJSON) else { clockBlink = !clockBlink; - if (!clockFatFont && !clockLargeFont) + if (!clockFontIsLarge) { sprintf_P(time, PSTR("%2d:%02d %s"), hourFormat12(), minute(), isAM() ? "AM" : "PM"); } @@ -2488,7 +2495,7 @@ void DrawClock(bool fromJSON) { clockCounterDate = 0; - if (clockFatFont || clockLargeFont) // fade rather than vertical animate purely because DrawTextCenter doesnt have a Y argument... + if (clockFontIsLarge) // fade rather than vertical animate purely because DrawTextCenter doesnt have a Y argument... { DrawTextCenter(String(time), clockFontChoise, clockColorR, clockColorG, clockColorB, 0, 1); FadeOut(30); @@ -2515,7 +2522,7 @@ void DrawClock(bool fromJSON) } } } - else if (clockFatFont || clockLargeFont) + else if (clockFontIsLarge) { DrawTextCenter(String(time), clockFontChoise, clockColorR, clockColorG, clockColorB, 0, 1); @@ -2534,7 +2541,7 @@ void DrawClock(bool fromJSON) { clockCounterClock = 0; - if (clockFatFont || clockLargeFont) // fade rather than vertical animate purely because DrawTextCenter doesnt have a Y argument... + if (clockFontIsLarge) // fade rather than vertical animate purely because DrawTextCenter doesnt have a Y argument... { DrawTextCenter(String(date), 2, clockColorR, clockColorG, clockColorB, 0, 1); FadeOut(30); @@ -2561,7 +2568,7 @@ void DrawClock(bool fromJSON) } } } - else if (clockFatFont || clockLargeFont) + else if (clockFontIsLarge) { DrawTextCenter(String(date), clockFontChoise, clockColorR, clockColorG, clockColorB, 0, 1); } @@ -2571,7 +2578,7 @@ void DrawClock(bool fromJSON) } } - if (!clockFatFont && !clockLargeFont && clockDrawWeekDays) + if (!clockFontIsLarge && clockDrawWeekDays) { DrawWeekDay(); } From 79f3f81030ff7045d2e79f314101a32a884a9277 Mon Sep 17 00:00:00 2001 From: Jeka Der Date: Sat, 28 Oct 2023 19:33:55 +0200 Subject: [PATCH 04/13] enable 7px default large clock font --- src/PixelIt.ino | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/PixelIt.ino b/src/PixelIt.ino index c2c1fcb..24b5ff7 100644 --- a/src/PixelIt.ino +++ b/src/PixelIt.ino @@ -293,7 +293,6 @@ uint8_t clockColorR = 255, clockColorG = 255, clockColorB = 255; uint clockAutoFallbackTime = 30; bool forceClock = false; bool clockBlinkAnimated = true; -uint clockFontChoise = 2; bool clockLargeFont = false; bool clockFatFont = false; bool clockDrawWeekDays = true; @@ -2415,7 +2414,18 @@ void DrawClock(bool fromJSON) int xPosTime = 0; - // check if a large font is in use + // use Adafruit 7px font as large clock font by default + uint clockFontChoice = 1; + if (clockFatFont) // use fat 8px clock font if set explicitly + { + clockFontChoice = 2; + } + else if (clockLargeFont) // use large 8px clock font if set explicitly + { + clockFontChoice = 3; + } + + // check if a large font is set bool clockFontIsLarge = false; if (clockLargeFont || clockFatFont) { @@ -2487,20 +2497,16 @@ void DrawClock(bool fromJSON) { clockCounterClock++; } - if (clockLargeFont) // use non-bold font - { - clockFontChoise = 3; - } if (clockCounterClock > clockSwitchSec) { clockCounterDate = 0; if (clockFontIsLarge) // fade rather than vertical animate purely because DrawTextCenter doesnt have a Y argument... { - DrawTextCenter(String(time), clockFontChoise, clockColorR, clockColorG, clockColorB, 0, 1); + DrawTextCenter(String(time), clockFontChoice, clockColorR, clockColorG, clockColorB, 0, 1); FadeOut(30); matrix->clear(); - DrawTextCenter(String(date), clockFontChoise, clockColorR, clockColorG, clockColorB, 0, 1); + DrawTextCenter(String(date), clockFontChoice, clockColorR, clockColorG, clockColorB, 0, 1); FadeIn(30); } else @@ -2525,7 +2531,7 @@ void DrawClock(bool fromJSON) else if (clockFontIsLarge) { - DrawTextCenter(String(time), clockFontChoise, clockColorR, clockColorG, clockColorB, 0, 1); + DrawTextCenter(String(time), clockFontChoice, clockColorR, clockColorG, clockColorB, 0, 1); } else { @@ -2570,7 +2576,7 @@ void DrawClock(bool fromJSON) } else if (clockFontIsLarge) { - DrawTextCenter(String(date), clockFontChoise, clockColorR, clockColorG, clockColorB, 0, 1); + DrawTextCenter(String(date), clockFontChoice, clockColorR, clockColorG, clockColorB, 0, 1); } else { From 3b4094e4a12d74fb7be18a00a2061f23506da6dc Mon Sep 17 00:00:00 2001 From: Dennis Rathjen Date: Fri, 3 Nov 2023 23:11:41 +0100 Subject: [PATCH 05/13] merge main to dev (#326) * Closes #259 * Fixed contributor action * Updated readme with new contributors * Switched to username for contributors * Updated readme with new contributors * Bump actions/setup-node from 3 to 4 (#325) Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3 to 4. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-node dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] Co-authored-by: foorschtbar Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-and-release.yml | 2 +- .github/workflows/contribute.yml | 6 +++- README.md | 47 ++++++++++++++----------- 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml index d914669..28885d4 100644 --- a/.github/workflows/build-and-release.yml +++ b/.github/workflows/build-and-release.yml @@ -15,7 +15,7 @@ jobs: repository: "pixelit-project/WebUI" - name: Use Node.js 💾 - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 19.x diff --git a/.github/workflows/contribute.yml b/.github/workflows/contribute.yml index 9eb8d9b..d7baba1 100644 --- a/.github/workflows/contribute.yml +++ b/.github/workflows/contribute.yml @@ -10,5 +10,9 @@ jobs: steps: - name: Contribute List uses: akhilmhdh/contributors-readme-action@v2.3.6 + with: + auto_detect_branch_protection: false + commit_message: "Updated readme with new contributors" + use_username: true env: - GITHUB_TOKEN: ${{ secrets.ACTION_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index 45b9313..c754813 100644 --- a/README.md +++ b/README.md @@ -30,78 +30,85 @@ Thanks to these great people for supporting this project. o0shojo0o
- Dennis Rathjen + o0shojo0o
foorschtbar
- Fab!an + foorschtbar
miccgn
- Miccgn + miccgn +
+ + + + Metaln00b +
+ Metaln00b
pplucky
- Pplucky + pplucky
+ + + jekader +
+ jekader +
+ + fmunozs
- Fernando Muñoz + fmunozs
rozza-m
- Rozza-m + rozza-m
- - + hermannbach
- HBach + hermannbach
d4rkd3v1l
- Martin Straub + d4rkd3v1l
hamster65
- Hamster65 -
- - - - jekader -
- Null + hamster65
rliegmann
- Rliegmann + rliegmann
@@ -111,7 +118,7 @@ Thanks to these great people for supporting this project. -### 2.4.x **WORK IN PROGRESS** +### 2.4.3 (2023-10-17) - (foorschtbar) Native support for [Ulanzi TC001 Pixel Clock](https://www.ulanzi.com/products/ulanzi-pixel-smart-clock-2882?aff=1181)\* :tada: - (foorschtbar) Display `zZz` on the matrix when the device going to sleep From 553c9129cb3436e80230279d078ad5df82bbd057 Mon Sep 17 00:00:00 2001 From: Dennis Rathjen Date: Fri, 3 Nov 2023 23:26:39 +0100 Subject: [PATCH 06/13] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index c754813..441118f 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,11 @@ Thanks to these great people for supporting this project. +### WORK IN PROGRESS + +- (o0shojo0o) Added Statistics to WebUi +- (jekader) Added large 8px non-bold clock font [[#320](https://github.com/pixelit-project/PixelIt/pull/320)] + ### 2.4.3 (2023-10-17) - (foorschtbar) Native support for [Ulanzi TC001 Pixel Clock](https://www.ulanzi.com/products/ulanzi-pixel-smart-clock-2882?aff=1181)\* :tada: From c7708d3af687b8abd9ddc32e3b493cfc8c38b557 Mon Sep 17 00:00:00 2001 From: Dennis Rathjen Date: Sat, 4 Nov 2023 15:36:28 +0100 Subject: [PATCH 07/13] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 441118f..5db4b95 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,7 @@ Thanks to these great people for supporting this project. ### WORK IN PROGRESS +- (o0shojo0o) Added config backup and restore [[#319](https://github.com/pixelit-project/PixelIt/issues/319)] - (o0shojo0o) Added Statistics to WebUi - (jekader) Added large 8px non-bold clock font [[#320](https://github.com/pixelit-project/PixelIt/pull/320)] From 260defff497d1af073477b1c232705f4bd9218cf Mon Sep 17 00:00:00 2001 From: Dennis Rathjen Date: Sat, 4 Nov 2023 16:21:16 +0100 Subject: [PATCH 08/13] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5db4b95..ee86fc1 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,8 @@ Thanks to these great people for supporting this project. ### WORK IN PROGRESS -- (o0shojo0o) Added config backup and restore [[#319](https://github.com/pixelit-project/PixelIt/issues/319)] +- (o0shojo0o) Also now in the WebUI Improved check of new firmware through a real version comparison +- (o0shojo0o) Added config backup and restore to WebUi [[#319](https://github.com/pixelit-project/PixelIt/issues/319)] - (o0shojo0o) Added Statistics to WebUi - (jekader) Added large 8px non-bold clock font [[#320](https://github.com/pixelit-project/PixelIt/pull/320)] From 360c8f1f0b36abfbd40e384260b9f674a3d63cd2 Mon Sep 17 00:00:00 2001 From: Dennis Rathjen Date: Sat, 4 Nov 2023 16:21:40 +0100 Subject: [PATCH 09/13] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ee86fc1..9d89a4f 100644 --- a/README.md +++ b/README.md @@ -121,8 +121,8 @@ Thanks to these great people for supporting this project. ### WORK IN PROGRESS - (o0shojo0o) Also now in the WebUI Improved check of new firmware through a real version comparison -- (o0shojo0o) Added config backup and restore to WebUi [[#319](https://github.com/pixelit-project/PixelIt/issues/319)] -- (o0shojo0o) Added Statistics to WebUi +- (o0shojo0o) Added config backup and restore to WebUI [[#319](https://github.com/pixelit-project/PixelIt/issues/319)] +- (o0shojo0o) Added Statistics to WebUI - (jekader) Added large 8px non-bold clock font [[#320](https://github.com/pixelit-project/PixelIt/pull/320)] ### 2.4.3 (2023-10-17) From b5a69ef88aa196c45bd47ed8d9750cb4cc4e39fe Mon Sep 17 00:00:00 2001 From: foorschtbar Date: Mon, 6 Nov 2023 11:28:12 +0100 Subject: [PATCH 10/13] Fixed JSON length mismatch function --- src/PixelIt.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PixelIt.ino b/src/PixelIt.ino index 24b5ff7..aac1632 100644 --- a/src/PixelIt.ino +++ b/src/PixelIt.ino @@ -1149,9 +1149,9 @@ void callback(char *topic, byte *payload, unsigned int length) Log("MQTT_callback", "Incoming JSON (Topic: " + String(topic) + ", Length: " + String(length) + "/" + String(json.measureLength()) + ") "); - if (length != json.measureLength()) + if (json.measureLength() == 2) { - Log("MQTT_callback", "JSON length mismatch! JSON Message to long :("); + Log("MQTT_callback", "JSON message empty or too long"); return; } if (channel.equals("setScreen")) From ee62277b4aa2d5f217f4abb600109fb12c084bfb Mon Sep 17 00:00:00 2001 From: Dennis Rathjen Date: Sun, 12 Nov 2023 12:57:05 +0100 Subject: [PATCH 11/13] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index d43a207..b7e2682 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,8 @@ Thanks to these great people for supporting this project. ### WORK IN PROGRESS +- (foorschtbar) Fixes "MQTT message is to long" [[#322](https://github.com/pixelit-project/PixelIt/issues/322)] +- (o0shojo0o) Adjustments in the WebUI for the new API structure of the UserMap endpoint - (o0shojo0o) Also now in the WebUI Improved check of new firmware through a real version comparison - (o0shojo0o) Added config backup and restore to WebUI [[#319](https://github.com/pixelit-project/PixelIt/issues/319)] - (o0shojo0o) Added Statistics to WebUI From d4db2cb87513e3f94d633963d3f929c83a2c80e8 Mon Sep 17 00:00:00 2001 From: foorschtbar Date: Sun, 12 Nov 2023 19:15:50 +0100 Subject: [PATCH 12/13] Added deviceTopic, make HA discovery optional and other minor improvments --- src/PixelIt.ino | 897 +++++++++++++++++++++++++++--------------------- 1 file changed, 513 insertions(+), 384 deletions(-) diff --git a/src/PixelIt.ino b/src/PixelIt.ino index aac1632..e49e168 100644 --- a/src/PixelIt.ino +++ b/src/PixelIt.ino @@ -89,6 +89,9 @@ String mqttUser = ""; String mqttPassword = ""; String mqttServer = ""; String mqttMasterTopic = "pixelit/"; +String mqttDeviceTopic = ""; +bool mqttUseDeviceTopic = true; +bool mqttHAdiscoverable = true; int mqttPort = 1883; unsigned long mqttLastReconnectAttempt = 0; // will store last time reconnect to mqtt broker const int MQTT_RECONNECT_INTERVAL = 15000; @@ -246,6 +249,7 @@ int mbaLuxMax = 400; int matrixType = DEFAULT_MATRIX_TYPE; String note; String hostname; +String deviceID; String matrixTempCorrection = "default"; // System Vars @@ -398,7 +402,7 @@ Version parseVersion(const char *versionStr) memset(version.prerelease, 0, sizeof(version.prerelease)); - int x = sscanf(versionStr, "%d.%d.%d-%s", &version.major, &version.minor, &version.patch, version.prerelease); + sscanf(versionStr, "%d.%d.%d-%s", &version.major, &version.minor, &version.patch, version.prerelease); return version; } @@ -467,7 +471,7 @@ void getBatteryVoltage() } } -void SetCurrentMatrixBrightness(float newBrightness) +void SetCurrentMatrixBrightness(int newBrightness) { currentMatrixBrightness = newBrightness; matrix->setBrightness(currentMatrixBrightness); @@ -531,6 +535,8 @@ void SaveConfig() json["mqttServer"] = mqttServer; json["mqttMasterTopic"] = mqttMasterTopic; json["mqttPort"] = mqttPort; + json["mqttUseDeviceTopic"] = mqttUseDeviceTopic; + json["mqttHAdiscoverable"] = mqttHAdiscoverable; json["luxOffset"] = luxOffset; json["temperatureOffset"] = temperatureOffset; json["humidityOffset"] = humidityOffset; @@ -645,7 +651,7 @@ void SetConfigVariables(JsonObject &json) if (json.containsKey("matrixBrightness")) { - SetCurrentMatrixBrightness(json["matrixBrightness"].as()); + SetCurrentMatrixBrightness(json["matrixBrightness"].as()); } if (json.containsKey("matrixType")) @@ -667,10 +673,6 @@ void SetConfigVariables(JsonObject &json) if ((hostname_raw.charAt(n) >= '0' && hostname_raw.charAt(n) <= '9') || (hostname_raw.charAt(n) >= 'A' && hostname_raw.charAt(n) <= 'Z') || (hostname_raw.charAt(n) >= 'a' && hostname_raw.charAt(n) <= 'z') || (hostname_raw.charAt(n) == '_') || (hostname_raw.charAt(n) == '-')) hostname += hostname_raw.charAt(n); } - if (hostname.isEmpty()) - { - hostname = "PixelIt"; - } } if (json.containsKey("matrixTempCorrection")) @@ -817,6 +819,16 @@ void SetConfigVariables(JsonObject &json) mqttPort = json["mqttPort"].as(); } + if (json.containsKey("mqttUseDeviceTopic")) + { + mqttUseDeviceTopic = json["mqttUseDeviceTopic"].as(); + } + + if (json.containsKey("mqttHAdiscoverable")) + { + mqttHAdiscoverable = json["mqttHAdiscoverable"].as(); + } + if (json.containsKey("luxOffset")) { luxOffset = json["luxOffset"].as(); @@ -1090,6 +1102,10 @@ void HandleAndSendButtonPress(uint button, bool state) if (mqttAktiv == true && client.connected()) { client.publish((mqttMasterTopic + "buttons/button" + String(button)).c_str(), (state ? "true" : "false"), true); + if (mqttUseDeviceTopic) + { + client.publish((mqttDeviceTopic + "buttons/button" + String(button)).c_str(), (state ? "true" : "false"), true); + } } // Prüfen ob über Websocket versendet werden muss if (webSocket.connectedClients() > 0) @@ -1142,12 +1158,16 @@ void callback(char *topic, byte *payload, unsigned int length) { payload[length] = '\0'; String channel = String(topic); - channel.replace(mqttMasterTopic, ""); + int lastSlashIndex = channel.lastIndexOf('/'); + if (lastSlashIndex != -1) + { + channel = channel.substring(lastSlashIndex + 1); + } DynamicJsonBuffer jsonBuffer; JsonObject &json = jsonBuffer.parseObject(payload); - Log("MQTT_callback", "Incoming JSON (Topic: " + String(topic) + ", Length: " + String(length) + "/" + String(json.measureLength()) + ") "); + Log("MQTT_callback", "Incoming JSON (Topic: " + String(topic) + ", Cmd: " + channel + ", Bytes: " + String(length) + "/" + String(json.measureLength()) + ") "); if (json.measureLength() == 2) { @@ -1161,14 +1181,26 @@ void callback(char *topic, byte *payload, unsigned int length) else if (channel.equals("getLuxsensor")) { client.publish((mqttMasterTopic + "luxsensor").c_str(), GetLuxSensor().c_str()); + if (mqttUseDeviceTopic) + { + client.publish((mqttDeviceTopic + "luxsensor").c_str(), GetLuxSensor().c_str()); + } } else if (channel.equals("getMatrixinfo")) { client.publish((mqttMasterTopic + "matrixinfo").c_str(), GetMatrixInfo().c_str()); + if (mqttUseDeviceTopic) + { + client.publish((mqttDeviceTopic + "matrixinfo").c_str(), GetMatrixInfo().c_str()); + } } else if (channel.equals("getConfig")) { client.publish((mqttMasterTopic + "config").c_str(), GetConfig().c_str()); + if (mqttUseDeviceTopic) + { + client.publish((mqttDeviceTopic + "config").c_str(), GetConfig().c_str()); + } } else if (channel.equals("setConfig")) { @@ -1285,47 +1317,51 @@ void CreateFrames(JsonObject &json) void CreateFrames(JsonObject &json, int forceDuration) { + bool sendMatrixInfo = false; + + String logMessage = F("JSON contains "); if (json.containsKey("sleepMode")) { + logMessage += F("Sleep Control, "); Serial.printf("SleepMode: %s\n", json["sleepMode"].as() ? "true" : "false"); // Update internal sleep state bool newSleepMode = json["sleepMode"].as(); - if (newSleepMode == sleepMode) - { - // Nothing to do - return; - } - else + if (newSleepMode != sleepMode) { + sendMatrixInfo = true; // Update sleep mode sleepMode = newSleepMode; - } - // Display sleepscreen - SleepScreen(sleepMode, false); + // Display sleepscreen + SleepScreen(sleepMode, false); - // Restore last frame if sleep mode is disabled - if (sleepMode == false) - { - DynamicJsonBuffer jsonBuffer; - JsonObject &tmpJson = jsonBuffer.parseObject(currentScreenJsonBuffer); - CreateFrames(tmpJson); + // Restore last frame if sleep mode is disabled + if (sleepMode == false && currentScreenJsonBuffer.length() > 0) + { + DynamicJsonBuffer jsonBuffer; + JsonObject &tmpJson = jsonBuffer.parseObject(currentScreenJsonBuffer); + CreateFrames(tmpJson); + return; + } } - - return; } - String logMessage = F("JSON contains "); - // Ist eine Display Helligkeit übergeben worden? - if (json.containsKey("brightness")) + if (json.containsKey("brightness") && !sleepMode) { logMessage += F("Brightness Control, "); - currentMatrixBrightness = json["brightness"]; + + if (json["brightness"].as() != currentMatrixBrightness) + { + sendMatrixInfo = true; + currentMatrixBrightness = json["brightness"].as(); + matrix->setBrightness(currentMatrixBrightness); + matrix->show(); + } } // Set GPIO @@ -1430,7 +1466,11 @@ void CreateFrames(JsonObject &json, int forceDuration) } } - if (!sleepMode && (millis() >= forcedScreenIsActiveUntil || forceDuration > 0)) + // Process screen content if + // - no sleepmode control is in message + // - not sleeping + // - no forced screen is active OR forceDuration is set + if (!json.containsKey("sleepMode") && !sleepMode && (millis() >= forcedScreenIsActiveUntil || forceDuration > 0)) { matrix->setBrightness(currentMatrixBrightness); @@ -1523,7 +1563,7 @@ void CreateFrames(JsonObject &json, int forceDuration) // Clock if (json.containsKey("clock")) { - logMessage += F("InternalClock Control, Params: "); + logMessage += F("InternalClock Control, Params: ("); scrollTextAktivLoop = false; animateBMPAktivLoop = false; clockAktiv = true; @@ -1590,6 +1630,11 @@ void CreateFrames(JsonObject &json, int forceDuration) logMessage += F("hexColor, "); ColorConverter::HexToRgb(json["clock"]["hexColor"].as(), clockColorR, clockColorG, clockColorB); } + if (logMessage.endsWith(", ")) + { + logMessage.remove(logMessage.length() - 2); + } + logMessage += F("), "); DrawClock(true); } @@ -1674,9 +1719,8 @@ void CreateFrames(JsonObject &json, int forceDuration) for (JsonVariant singleBitmap : json["bitmaps"].as()) { DrawSingleBitmap(singleBitmap); - logMessage += F("Bitmap,"); - } - + } + logMessage += json["bitmaps"].as().size(); logMessage += F("), "); } @@ -1743,7 +1787,7 @@ void CreateFrames(JsonObject &json, int forceDuration) bool scrollTextAktiv = false; if (json.containsKey("text")) { - logMessage += F("Text"); + logMessage += F("Text, "); // Always assume the default delay first. scrollTextDelay = scrollTextDefaultDelay; @@ -1808,19 +1852,25 @@ void CreateFrames(JsonObject &json, int forceDuration) matrix->show(); } } - else + + if (sleepMode && !json.containsKey("sleepMode")) { - logMessage += F("skipped, because an forced screen is currently being displayed."); + logMessage += F("[not all data processed because sleepMode is active]"); } - Log(F("CreateFrames"), logMessage + " (Length: " + json.measureLength() + ")"); + if (logMessage.endsWith(", ")) + { + logMessage.remove(logMessage.length() - 2); + logMessage += F(" "); + } + Log(F("CreateFrames"), logMessage + "(Length: " + json.measureLength() + ")"); if (forceDuration > 0 && (json.containsKey("bitmap") || json.containsKey("bitmaps") || json.containsKey("text") || json.containsKey("bar") || json.containsKey("bars") || json.containsKey("bitmapAnimation"))) { forcedScreenIsActiveUntil = millis() + forceDuration; } - if (!json.containsKey("sleepMode")) + if (!json.containsKey("sleepMode") && !sleepMode) { // Store last frame @@ -1832,6 +1882,11 @@ void CreateFrames(JsonObject &json, int forceDuration) currentScreenJsonBuffer = ""; json.printTo(currentScreenJsonBuffer); } + + if (sendMatrixInfo) + { + SendMatrixInfo(); + } } String GetConfig() @@ -2047,6 +2102,7 @@ String GetMatrixInfo() //// Matrix Config root["note"] = note; root["hostname"] = hostname; + root["deviceID"] = deviceID; root["buildSection"] = STR(BUILD_SECTION); root["freeSketchSpace"] = ESP.getFreeSketchSpace(); root["wifiRSSI"] = WiFi.RSSI(); @@ -2648,381 +2704,431 @@ boolean MQTTreconnect() client.subscribe((mqttMasterTopic + "getMatrixinfo").c_str()); client.subscribe((mqttMasterTopic + "getConfig").c_str()); client.subscribe((mqttMasterTopic + "setConfig").c_str()); + if (mqttUseDeviceTopic) + { + client.subscribe((mqttDeviceTopic + "setScreen").c_str()); + client.subscribe((mqttDeviceTopic + "getLuxsensor").c_str()); + client.subscribe((mqttDeviceTopic + "getMatrixinfo").c_str()); + client.subscribe((mqttDeviceTopic + "getConfig").c_str()); + client.subscribe((mqttDeviceTopic + "setConfig").c_str()); + } // ... and publish state .... client.publish((mqttMasterTopic + "state").c_str(), "connected", true); + if (mqttUseDeviceTopic) + { + client.publish((mqttDeviceTopic + "state").c_str(), "connected", true); + } // ... and provide discovery information // Create discovery information for Homeassistant // Can also be processed by ioBroker, OpenHAB etc. - String deviceID = hostname; - if (deviceID.isEmpty()) - deviceID = "pixelit"; -#if defined(ESP8266) - deviceID += ESP.getChipId(); -#elif defined(ESP32) - deviceID += uint64ToString(ESP.getEfuseMac()); -#endif - // Get host IP to provide URL in MQTT discovery device info - String ip_url = "http://" + WiFi.localIP().toString(); - String configTopicTemplate = String(F("homeassistant/#COMPONENT#/#DEVICEID#/#DEVICEID##SENSORID#/config")); - configTopicTemplate.replace(F("#DEVICEID#"), deviceID); - String configPayloadTemplate = String(F( - "{" - "\"dev\":{" - "\"ids\":\"#DEVICEID#\"," - "\"name\":\"#HOSTNAME#\"," - "\"mdl\":\"PixelIt\"," - "\"mf\":\"PixelIt\"," - "\"sw\":\"#VERSION#\"," - "\"cu\":\"#IP#\"" - "}," - "\"avty_t\":\"#MASTERTOPIC#state\"," - "\"pl_avail\":\"connected\"," - "\"pl_not_avail\":\"disconnected\"," - "\"uniq_id\":\"#DEVICEID##SENSORID#\"," - "\"dev_cla\":\"#CLASS#\"," - "\"name\":\"#SENSORNAME#\"," - "\"stat_t\":\"#MASTERTOPIC##STATETOPIC#\"," - "\"unit_of_meas\":\"#UNIT#\"," - "\"val_tpl\":\"{{value_json.#VALUENAME#}}\"" - "}")); - configPayloadTemplate.replace(" ", ""); - configPayloadTemplate.replace(F("#DEVICEID#"), deviceID); - configPayloadTemplate.replace(F("#HOSTNAME#"), hostname); - configPayloadTemplate.replace(F("#VERSION#"), VERSION); - configPayloadTemplate.replace(F("#MASTERTOPIC#"), mqttMasterTopic); - configPayloadTemplate.replace(F("#IP#"), ip_url); - - String topic; - String payload; - - if (tempSensor != TempSensor_None) + if (mqttHAdiscoverable) { + + // Get host IP to provide URL in MQTT discovery device info + String ip_url = "http://" + WiFi.localIP().toString(); + String configTopicTemplate = String(F("homeassistant/#COMPONENT#/#DEVICEID#/#DEVICEID##SENSORID#/config")); + configTopicTemplate.replace(F("#DEVICEID#"), deviceID); + String configPayloadTemplate = String(F( + "{" + "\"dev\":{" + "\"ids\":\"#DEVICEID#\"," + "\"name\":\"#HOSTNAME#\"," + "\"mdl\":\"PixelIt\"," + "\"mf\":\"PixelIt\"," + "\"sw\":\"#VERSION#\"," + "\"cu\":\"#IP#\"" + "}," + "\"avty_t\":\"#MASTERTOPIC#state\"," + "\"pl_avail\":\"connected\"," + "\"pl_not_avail\":\"disconnected\"," + "\"uniq_id\":\"#DEVICEID##SENSORID#\"," + "\"dev_cla\":\"#CLASS#\"," + "\"name\":\"#SENSORNAME#\"," + "\"stat_t\":\"#MASTERTOPIC##STATETOPIC#\"," + "\"unit_of_meas\":\"#UNIT#\"," + "\"val_tpl\":\"{{value_json.#VALUENAME#}}\"" + "}")); + configPayloadTemplate.replace(" ", ""); + configPayloadTemplate.replace(F("#DEVICEID#"), deviceID); + configPayloadTemplate.replace(F("#HOSTNAME#"), hostname); + configPayloadTemplate.replace(F("#VERSION#"), VERSION); + if (mqttUseDeviceTopic) + { + configPayloadTemplate.replace(F("#MASTERTOPIC#"), mqttDeviceTopic); + } + else + { + configPayloadTemplate.replace(F("#MASTERTOPIC#"), mqttMasterTopic); + } + configPayloadTemplate.replace(F("#IP#"), ip_url); + + String topic; + String payload; + + if (tempSensor != TempSensor_None) + { + topic = configTopicTemplate; + topic.replace(F("#COMPONENT#"), F("sensor")); + topic.replace(F("#SENSORID#"), F("Temperature")); + + payload = configPayloadTemplate; + payload.replace(F("#SENSORID#"), F("Temperature")); + payload.replace(F("#SENSORNAME#"), F("Temperature")); + payload.replace(F("#CLASS#"), F("temperature")); + payload.replace(F("#STATETOPIC#"), F("sensor")); + payload.replace(F("#UNIT#"), "°C"); + payload.replace(F("#VALUENAME#"), F("temperature")); + client.publish(topic.c_str(), payload.c_str(), true); + + topic = configTopicTemplate; + topic.replace(F("#COMPONENT#"), F("sensor")); + topic.replace(F("#SENSORID#"), F("Humidity")); + + payload = configPayloadTemplate; + payload.replace(F("#SENSORNAME#"), F("Humidity")); + payload.replace(F("#CLASS#"), F("humidity")); + payload.replace(F("#STATETOPIC#"), F("sensor")); + payload.replace(F("#UNIT#"), "%"); + payload.replace(F("#VALUENAME#"), F("humidity")); + client.publish(topic.c_str(), payload.c_str(), true); + } + if (tempSensor == TempSensor_BME280 || tempSensor == TempSensor_BMP280 || tempSensor == TempSensor_BME680) + { + topic = configTopicTemplate; + topic.replace(F("#COMPONENT#"), F("sensor")); + topic.replace(F("#SENSORID#"), F("Pressure")); + + payload = configPayloadTemplate; + payload.replace(F("#SENSORID#"), F("Pressure")); + payload.replace(F("#SENSORNAME#"), F("Pressure")); + payload.replace(F("#CLASS#"), F("pressure")); + payload.replace(F("#STATETOPIC#"), F("sensor")); + payload.replace(F("#UNIT#"), "hPa"); + payload.replace(F("#VALUENAME#"), F("pressure")); + client.publish(topic.c_str(), payload.c_str(), true); + } + + if (tempSensor == TempSensor_BME680) + { + topic = configTopicTemplate; + topic.replace(F("#COMPONENT#"), F("sensor")); + topic.replace(F("#SENSORID#"), F("VOC")); + + payload = configPayloadTemplate; + payload.replace(F("#SENSORID#"), F("VOC")); + payload.replace(F("#SENSORNAME#"), F("VOC")); + payload.replace(F("#CLASS#"), F("volatile_organic_compounds")); + payload.replace(F("#STATETOPIC#"), F("sensor")); + payload.replace(F("#UNIT#"), "kOhm"); + payload.replace(F("#VALUENAME#"), F("gas")); + client.publish(topic.c_str(), payload.c_str(), true); + } topic = configTopicTemplate; topic.replace(F("#COMPONENT#"), F("sensor")); - topic.replace(F("#SENSORID#"), F("Temperature")); + topic.replace(F("#SENSORID#"), F("Illuminance")); payload = configPayloadTemplate; - payload.replace(F("#SENSORID#"), F("Temperature")); - payload.replace(F("#SENSORNAME#"), F("Temperature")); - payload.replace(F("#CLASS#"), F("temperature")); - payload.replace(F("#STATETOPIC#"), F("sensor")); - payload.replace(F("#UNIT#"), "°C"); - payload.replace(F("#VALUENAME#"), F("temperature")); + payload.replace(F("#SENSORID#"), F("Illuminance")); + payload.replace(F("#SENSORNAME#"), F("Illuminance")); + payload.replace(F("#CLASS#"), F("illuminance")); + payload.replace(F("#STATETOPIC#"), F("luxsensor")); + payload.replace(F("#UNIT#"), "lx"); + payload.replace(F("#VALUENAME#"), F("lux")); client.publish(topic.c_str(), payload.c_str(), true); + configPayloadTemplate = String(F( + "{" + "\"dev\":{" + "\"ids\":\"#DEVICEID#\"," + "\"name\":\"#HOSTNAME#\"," + "\"mdl\":\"PixelIt\"," + "\"mf\":\"PixelIt\"," + "\"sw\":\"#VERSION#\"," + "\"cu\":\"#IP#\"" + "}," + "\"avty_t\":\"#MASTERTOPIC#state\"," + "\"pl_avail\":\"connected\"," + "\"pl_not_avail\":\"disconnected\"," + "\"uniq_id\":\"#DEVICEID##SENSORID#\"," + "\"name\":\"#SENSORNAME#\"," + "\"ic\":\"mdi:gesture-tap-button\"," + "\"pl_on\":\"true\"," + "\"pl_off\":\"false\"," + "\"stat_t\":\"#MASTERTOPIC##STATETOPIC#\"" + "}")); + configPayloadTemplate.replace(" ", ""); + configPayloadTemplate.replace(F("#DEVICEID#"), deviceID); + configPayloadTemplate.replace(F("#HOSTNAME#"), hostname); + configPayloadTemplate.replace(F("#VERSION#"), VERSION); + if (mqttUseDeviceTopic) + { + configPayloadTemplate.replace(F("#MASTERTOPIC#"), mqttDeviceTopic); + } + else + { + configPayloadTemplate.replace(F("#MASTERTOPIC#"), mqttMasterTopic); + } + configPayloadTemplate.replace(F("#IP#"), ip_url); + + for (uint8_t n = 0; n < sizeof(btnEnabled) / sizeof(btnEnabled[0]); n++) + { + if (btnEnabled[n]) + { + topic = configTopicTemplate; + topic.replace(F("#COMPONENT#"), F("binary_sensor")); + topic.replace(F("#SENSORID#"), String(F("Button")) + String(n)); + + payload = configPayloadTemplate; + payload.replace(F("#SENSORID#"), String(F("Button")) + String(n)); + payload.replace(F("#SENSORNAME#"), String(btnLogNames[n])); + payload.replace(F("#STATETOPIC#"), String(F("buttons/button")) + String(n)); + client.publish(topic.c_str(), payload.c_str(), true); + } + } + + // Wifi RSSI + configPayloadTemplate = String(F( + "{" + "\"dev\":{" + "\"ids\":\"#DEVICEID#\"," + "\"name\":\"#HOSTNAME#\"," + "\"mdl\":\"PixelIt\"," + "\"mf\":\"PixelIt\"," + "\"sw\":\"#VERSION#\"," + "\"cu\":\"#IP#\"" + "}," + "\"avty_t\":\"#MASTERTOPIC#state\"," + "\"pl_avail\":\"connected\"," + "\"pl_not_avail\":\"disconnected\"," + "\"uniq_id\":\"#DEVICEID##SENSORID#\"," + "\"dev_cla\":\"signal_strength\"," + "\"name\":\"#SENSORNAME#\"," + "\"stat_t\":\"#MASTERTOPIC##STATETOPIC#\"," + "\"unit_of_meas\":\"#UNIT#\"," + "\"val_tpl\":\"{{value_json.#VALUENAME#}}\"," + "\"ent_cat\":\"diagnostic\"," + "\"ic\":\"mdi:#ICON#\"," + "\"enabled_by_default\":\"false\"" + "}")); + configPayloadTemplate.replace(" ", ""); + configPayloadTemplate.replace(F("#DEVICEID#"), deviceID); + configPayloadTemplate.replace(F("#HOSTNAME#"), hostname); + configPayloadTemplate.replace(F("#VERSION#"), VERSION); + if (mqttUseDeviceTopic) + { + configPayloadTemplate.replace(F("#MASTERTOPIC#"), mqttDeviceTopic); + } + else + { + configPayloadTemplate.replace(F("#MASTERTOPIC#"), mqttMasterTopic); + } + configPayloadTemplate.replace(F("#IP#"), ip_url); + topic = configTopicTemplate; topic.replace(F("#COMPONENT#"), F("sensor")); - topic.replace(F("#SENSORID#"), F("Humidity")); + topic.replace(F("#SENSORID#"), F("wifiRSSI")); payload = configPayloadTemplate; - payload.replace(F("#SENSORNAME#"), F("Humidity")); - payload.replace(F("#CLASS#"), F("humidity")); - payload.replace(F("#STATETOPIC#"), F("sensor")); - payload.replace(F("#UNIT#"), "%"); - payload.replace(F("#VALUENAME#"), F("humidity")); + payload.replace(F("#SENSORID#"), F("wifiRSSI")); + payload.replace(F("#SENSORNAME#"), F("Wifi Signal")); + payload.replace(F("#CLASS#"), F("signal_strength")); + payload.replace(F("#STATETOPIC#"), F("matrixinfo")); + payload.replace(F("#UNIT#"), "dBm"); + payload.replace(F("#VALUENAME#"), F("wifiRSSI")); + payload.replace(F("#ICON#"), F("signal")); client.publish(topic.c_str(), payload.c_str(), true); - } - if (tempSensor == TempSensor_BME280 || tempSensor == TempSensor_BMP280 || tempSensor == TempSensor_BME680) - { + + // Wifi Quality sensor + configPayloadTemplate = String(F( + "{" + "\"dev\":{" + "\"ids\":\"#DEVICEID#\"," + "\"name\":\"#HOSTNAME#\"," + "\"mdl\":\"PixelIt\"," + "\"mf\":\"PixelIt\"," + "\"sw\":\"#VERSION#\"," + "\"cu\":\"#IP#\"" + "}," + "\"avty_t\":\"#MASTERTOPIC#state\"," + "\"pl_avail\":\"connected\"," + "\"pl_not_avail\":\"disconnected\"," + "\"uniq_id\":\"#DEVICEID##SENSORID#\"," + "\"name\":\"#SENSORNAME#\"," + "\"stat_t\":\"#MASTERTOPIC##STATETOPIC#\"," + "\"unit_of_meas\":\"#UNIT#\"," + "\"val_tpl\":\"{{value_json.#VALUENAME#}}\"," + "\"ent_cat\":\"diagnostic\"," + "\"ic\":\"mdi:#ICON#\"," + "\"enabled_by_default\":\"false\"" + "}")); + configPayloadTemplate.replace(" ", ""); + configPayloadTemplate.replace(F("#DEVICEID#"), deviceID); + configPayloadTemplate.replace(F("#HOSTNAME#"), hostname); + configPayloadTemplate.replace(F("#VERSION#"), VERSION); + if (mqttUseDeviceTopic) + { + configPayloadTemplate.replace(F("#MASTERTOPIC#"), mqttDeviceTopic); + } + else + { + configPayloadTemplate.replace(F("#MASTERTOPIC#"), mqttMasterTopic); + } + configPayloadTemplate.replace(F("#IP#"), ip_url); + topic = configTopicTemplate; topic.replace(F("#COMPONENT#"), F("sensor")); - topic.replace(F("#SENSORID#"), F("Pressure")); + topic.replace(F("#SENSORID#"), F("WifiQuality")); payload = configPayloadTemplate; - payload.replace(F("#SENSORID#"), F("Pressure")); - payload.replace(F("#SENSORNAME#"), F("Pressure")); - payload.replace(F("#CLASS#"), F("pressure")); - payload.replace(F("#STATETOPIC#"), F("sensor")); - payload.replace(F("#UNIT#"), "hPa"); - payload.replace(F("#VALUENAME#"), F("pressure")); + payload.replace(F("#SENSORID#"), F("WifiQuality")); + payload.replace(F("#SENSORNAME#"), F("Wifi Quality")); + payload.replace(F("#STATETOPIC#"), F("matrixinfo")); + payload.replace(F("#UNIT#"), "%"); + payload.replace(F("#VALUENAME#"), F("wifiQuality")); + payload.replace(F("#ICON#"), F("signal")); client.publish(topic.c_str(), payload.c_str(), true); - } - if (tempSensor == TempSensor_BME680) - { + // CPU Freq. topic = configTopicTemplate; topic.replace(F("#COMPONENT#"), F("sensor")); - topic.replace(F("#SENSORID#"), F("VOC")); + topic.replace(F("#SENSORID#"), F("cpuFreqMHz")); payload = configPayloadTemplate; - payload.replace(F("#SENSORID#"), F("VOC")); - payload.replace(F("#SENSORNAME#"), F("VOC")); - payload.replace(F("#CLASS#"), F("volatile_organic_compounds")); - payload.replace(F("#STATETOPIC#"), F("sensor")); - payload.replace(F("#UNIT#"), "kOhm"); - payload.replace(F("#VALUENAME#"), F("gas")); + payload.replace(F("#SENSORID#"), F("cpuFreqMHz")); + payload.replace(F("#SENSORNAME#"), F("CPU Freq.")); + payload.replace(F("#STATETOPIC#"), F("matrixinfo")); + payload.replace(F("#UNIT#"), "MHz"); + payload.replace(F("#VALUENAME#"), F("cpuFreqMHz")); + payload.replace(F("#ICON#"), F("developer-board")); client.publish(topic.c_str(), payload.c_str(), true); - } - topic = configTopicTemplate; - topic.replace(F("#COMPONENT#"), F("sensor")); - topic.replace(F("#SENSORID#"), F("Illuminance")); - - payload = configPayloadTemplate; - payload.replace(F("#SENSORID#"), F("Illuminance")); - payload.replace(F("#SENSORNAME#"), F("Illuminance")); - payload.replace(F("#CLASS#"), F("illuminance")); - payload.replace(F("#STATETOPIC#"), F("luxsensor")); - payload.replace(F("#UNIT#"), "lx"); - payload.replace(F("#VALUENAME#"), F("lux")); - client.publish(topic.c_str(), payload.c_str(), true); - - configPayloadTemplate = String(F( - "{" - "\"dev\":{" - "\"ids\":\"#DEVICEID#\"," - "\"name\":\"#HOSTNAME#\"," - "\"mdl\":\"PixelIt\"," - "\"mf\":\"PixelIt\"," - "\"sw\":\"#VERSION#\"," - "\"cu\":\"#IP#\"" - "}," - "\"avty_t\":\"#MASTERTOPIC#state\"," - "\"pl_avail\":\"connected\"," - "\"pl_not_avail\":\"disconnected\"," - "\"uniq_id\":\"#DEVICEID##SENSORID#\"," - "\"name\":\"#SENSORNAME#\"," - "\"ic\":\"mdi:gesture-tap-button\"," - "\"pl_on\":\"true\"," - "\"pl_off\":\"false\"," - "\"stat_t\":\"#MASTERTOPIC##STATETOPIC#\"" - "}")); - configPayloadTemplate.replace(" ", ""); - configPayloadTemplate.replace(F("#DEVICEID#"), deviceID); - configPayloadTemplate.replace(F("#HOSTNAME#"), hostname); - configPayloadTemplate.replace(F("#VERSION#"), VERSION); - configPayloadTemplate.replace(F("#MASTERTOPIC#"), mqttMasterTopic); - configPayloadTemplate.replace(F("#IP#"), ip_url); - - for (uint8_t n = 0; n < sizeof(btnEnabled) / sizeof(btnEnabled[0]); n++) - { - if (btnEnabled[n]) + + // Wifi SSID + configPayloadTemplate = String(F( + "{" + "\"dev\":{" + "\"ids\":\"#DEVICEID#\"," + "\"name\":\"#HOSTNAME#\"," + "\"mdl\":\"PixelIt\"," + "\"mf\":\"PixelIt\"," + "\"sw\":\"#VERSION#\"," + "\"cu\":\"#IP#\"" + "}," + "\"avty_t\":\"#MASTERTOPIC#state\"," + "\"pl_avail\":\"connected\"," + "\"pl_not_avail\":\"disconnected\"," + "\"uniq_id\":\"#DEVICEID##SENSORID#\"," + "\"name\":\"#SENSORNAME#\"," + "\"stat_t\":\"#MASTERTOPIC##STATETOPIC#\"," + "\"val_tpl\":\"{{value_json.#VALUENAME#}}\"," + "\"ent_cat\":\"diagnostic\"," + "\"ic\":\"mdi:#ICON#\"," + "\"enabled_by_default\":\"false\"" + "}")); + configPayloadTemplate.replace(" ", ""); + configPayloadTemplate.replace(F("#DEVICEID#"), deviceID); + configPayloadTemplate.replace(F("#HOSTNAME#"), hostname); + configPayloadTemplate.replace(F("#VERSION#"), VERSION); + if (mqttUseDeviceTopic) { - topic = configTopicTemplate; - topic.replace(F("#COMPONENT#"), F("binary_sensor")); - topic.replace(F("#SENSORID#"), String(F("Button")) + String(n)); + configPayloadTemplate.replace(F("#MASTERTOPIC#"), mqttDeviceTopic); + } + else + { + configPayloadTemplate.replace(F("#MASTERTOPIC#"), mqttMasterTopic); + } + configPayloadTemplate.replace(F("#IP#"), ip_url); - payload = configPayloadTemplate; - payload.replace(F("#SENSORID#"), String(F("Button")) + String(n)); - payload.replace(F("#SENSORNAME#"), String(btnLogNames[n])); - payload.replace(F("#STATETOPIC#"), String(F("buttons/button")) + String(n)); - client.publish(topic.c_str(), payload.c_str(), true); + topic = configTopicTemplate; + topic.replace(F("#COMPONENT#"), F("sensor")); + topic.replace(F("#SENSORID#"), F("WifiSSID")); + + payload = configPayloadTemplate; + payload.replace(F("#SENSORID#"), F("WifiSSID")); + payload.replace(F("#SENSORNAME#"), F("SSID")); + payload.replace(F("#STATETOPIC#"), F("matrixinfo")); + payload.replace(F("#VALUENAME#"), F("wifiSSID")); + payload.replace(F("#ICON#"), F("wifi")); + client.publish(topic.c_str(), payload.c_str(), true); + + // Wifi BSSID + topic = configTopicTemplate; + topic.replace(F("#COMPONENT#"), F("sensor")); + topic.replace(F("#SENSORID#"), F("WifiBSSID")); + + payload = configPayloadTemplate; + payload.replace(F("#SENSORID#"), F("WifiBSSID")); + payload.replace(F("#SENSORNAME#"), F("BSSID")); + payload.replace(F("#STATETOPIC#"), F("matrixinfo")); + payload.replace(F("#VALUENAME#"), F("wifiBSSID")); + payload.replace(F("#ICON#"), F("wifi")); + client.publish(topic.c_str(), payload.c_str(), true); + + // Chip ID + topic = configTopicTemplate; + topic.replace(F("#COMPONENT#"), F("sensor")); + topic.replace(F("#SENSORID#"), F("chipID")); + + payload = configPayloadTemplate; + payload.replace(F("#SENSORID#"), F("chipID")); + payload.replace(F("#SENSORNAME#"), F("Chip ID")); + payload.replace(F("#STATETOPIC#"), F("matrixinfo")); + payload.replace(F("#VALUENAME#"), F("chipID")); + payload.replace(F("#ICON#"), F("developer-board")); + client.publish(topic.c_str(), payload.c_str(), true); + + // LED Matrix on/off + brightness light + configPayloadTemplate = String(F( + "{" + "\"dev\":{" + "\"ids\":\"#DEVICEID#\"," + "\"name\":\"#HOSTNAME#\"," + "\"mdl\":\"PixelIt\"," + "\"mf\":\"PixelIt\"," + "\"sw\":\"#VERSION#\"," + "\"cu\":\"#IP#\"" + "}," + "\"avty_t\":\"#MASTERTOPIC#state\"," + "\"pl_avail\":\"connected\"," + "\"pl_not_avail\":\"disconnected\"," + "\"uniq_id\":\"#DEVICEID##SENSORID#\"," + "\"name\":\"#SENSORNAME#\"," + "\"schema\":\"template\"," + "\"stat_t\":\"#MASTERTOPIC##STATETOPIC#\"," + "\"stat_tpl\":\"{{ \'on\' if value_json.sleepMode is false else \'off\' }}\"," + "\"cmd_t\":\"#MASTERTOPIC##COMMANDTOPIC#\"," + "\"cmd_on_tpl\":\"{\\\"sleepMode\\\": false {%- if brightness is defined -%}, \\\"brightness\\\": {{ brightness }}{%- endif -%}}\"," + "\"cmd_off_tpl\":\"{\\\"sleepMode\\\": true}\"," + "\"bri_tpl\":\"{{ value_json.currentMatrixBrightness }}\"," + "\"icon\":\"mdi:#ICON#\"" + "}")); + configPayloadTemplate.replace(F("#DEVICEID#"), deviceID); + configPayloadTemplate.replace(F("#HOSTNAME#"), hostname); + configPayloadTemplate.replace(F("#VERSION#"), VERSION); + if (mqttUseDeviceTopic) + { + configPayloadTemplate.replace(F("#MASTERTOPIC#"), mqttDeviceTopic); } - } + else + { + configPayloadTemplate.replace(F("#MASTERTOPIC#"), mqttMasterTopic); + } + configPayloadTemplate.replace(F("#IP#"), ip_url); + + topic = configTopicTemplate; + topic.replace(F("#COMPONENT#"), F("light")); + topic.replace(F("#SENSORID#"), F("LEDMatrixLight")); + + payload = configPayloadTemplate; + payload.replace(F("#SENSORID#"), F("LEDMatrixLight")); + payload.replace(F("#SENSORNAME#"), F("LED Matrix")); + payload.replace(F("#STATETOPIC#"), F("matrixinfo")); + payload.replace(F("#COMMANDTOPIC#"), F("setScreen")); + payload.replace(F("#ICON#"), F("led-strip")); + client.publish(topic.c_str(), payload.c_str(), true); - // Wifi RSSI - configPayloadTemplate = String(F( - "{" - "\"dev\":{" - "\"ids\":\"#DEVICEID#\"," - "\"name\":\"#HOSTNAME#\"," - "\"mdl\":\"PixelIt\"," - "\"mf\":\"PixelIt\"," - "\"sw\":\"#VERSION#\"," - "\"cu\":\"#IP#\"" - "}," - "\"avty_t\":\"#MASTERTOPIC#state\"," - "\"pl_avail\":\"connected\"," - "\"pl_not_avail\":\"disconnected\"," - "\"uniq_id\":\"#DEVICEID##SENSORID#\"," - "\"dev_cla\":\"signal_strength\"," - "\"name\":\"#SENSORNAME#\"," - "\"stat_t\":\"#MASTERTOPIC##STATETOPIC#\"," - "\"unit_of_meas\":\"#UNIT#\"," - "\"val_tpl\":\"{{value_json.#VALUENAME#}}\"," - "\"ent_cat\":\"diagnostic\"," - "\"ic\":\"mdi:#ICON#\"," - "\"enabled_by_default\":\"false\"" - "}")); - configPayloadTemplate.replace(" ", ""); - configPayloadTemplate.replace(F("#DEVICEID#"), deviceID); - configPayloadTemplate.replace(F("#HOSTNAME#"), hostname); - configPayloadTemplate.replace(F("#VERSION#"), VERSION); - configPayloadTemplate.replace(F("#MASTERTOPIC#"), mqttMasterTopic); - configPayloadTemplate.replace(F("#IP#"), ip_url); - - topic = configTopicTemplate; - topic.replace(F("#COMPONENT#"), F("sensor")); - topic.replace(F("#SENSORID#"), F("wifiRSSI")); - - payload = configPayloadTemplate; - payload.replace(F("#SENSORID#"), F("wifiRSSI")); - payload.replace(F("#SENSORNAME#"), F("Wifi Signal")); - payload.replace(F("#CLASS#"), F("signal_strength")); - payload.replace(F("#STATETOPIC#"), F("matrixinfo")); - payload.replace(F("#UNIT#"), "dBm"); - payload.replace(F("#VALUENAME#"), F("wifiRSSI")); - payload.replace(F("#ICON#"), F("signal")); - client.publish(topic.c_str(), payload.c_str(), true); - - // Wifi Quality sensor - configPayloadTemplate = String(F( - "{" - "\"dev\":{" - "\"ids\":\"#DEVICEID#\"," - "\"name\":\"#HOSTNAME#\"," - "\"mdl\":\"PixelIt\"," - "\"mf\":\"PixelIt\"," - "\"sw\":\"#VERSION#\"," - "\"cu\":\"#IP#\"" - "}," - "\"avty_t\":\"#MASTERTOPIC#state\"," - "\"pl_avail\":\"connected\"," - "\"pl_not_avail\":\"disconnected\"," - "\"uniq_id\":\"#DEVICEID##SENSORID#\"," - "\"name\":\"#SENSORNAME#\"," - "\"stat_t\":\"#MASTERTOPIC##STATETOPIC#\"," - "\"unit_of_meas\":\"#UNIT#\"," - "\"val_tpl\":\"{{value_json.#VALUENAME#}}\"," - "\"ent_cat\":\"diagnostic\"," - "\"ic\":\"mdi:#ICON#\"," - "\"enabled_by_default\":\"false\"" - "}")); - configPayloadTemplate.replace(" ", ""); - configPayloadTemplate.replace(F("#DEVICEID#"), deviceID); - configPayloadTemplate.replace(F("#HOSTNAME#"), hostname); - configPayloadTemplate.replace(F("#VERSION#"), VERSION); - configPayloadTemplate.replace(F("#MASTERTOPIC#"), mqttMasterTopic); - configPayloadTemplate.replace(F("#IP#"), ip_url); - - topic = configTopicTemplate; - topic.replace(F("#COMPONENT#"), F("sensor")); - topic.replace(F("#SENSORID#"), F("WifiQuality")); - - payload = configPayloadTemplate; - payload.replace(F("#SENSORID#"), F("WifiQuality")); - payload.replace(F("#SENSORNAME#"), F("Wifi Quality")); - payload.replace(F("#STATETOPIC#"), F("matrixinfo")); - payload.replace(F("#UNIT#"), "%"); - payload.replace(F("#VALUENAME#"), F("wifiQuality")); - payload.replace(F("#ICON#"), F("signal")); - client.publish(topic.c_str(), payload.c_str(), true); - - // CPU Freq. - topic = configTopicTemplate; - topic.replace(F("#COMPONENT#"), F("sensor")); - topic.replace(F("#SENSORID#"), F("cpuFreqMHz")); - - payload = configPayloadTemplate; - payload.replace(F("#SENSORID#"), F("cpuFreqMHz")); - payload.replace(F("#SENSORNAME#"), F("CPU Freq.")); - payload.replace(F("#STATETOPIC#"), F("matrixinfo")); - payload.replace(F("#UNIT#"), "MHz"); - payload.replace(F("#VALUENAME#"), F("cpuFreqMHz")); - payload.replace(F("#ICON#"), F("developer-board")); - client.publish(topic.c_str(), payload.c_str(), true); - - // Wifi SSID - configPayloadTemplate = String(F( - "{" - "\"dev\":{" - "\"ids\":\"#DEVICEID#\"," - "\"name\":\"#HOSTNAME#\"," - "\"mdl\":\"PixelIt\"," - "\"mf\":\"PixelIt\"," - "\"sw\":\"#VERSION#\"," - "\"cu\":\"#IP#\"" - "}," - "\"avty_t\":\"#MASTERTOPIC#state\"," - "\"pl_avail\":\"connected\"," - "\"pl_not_avail\":\"disconnected\"," - "\"uniq_id\":\"#DEVICEID##SENSORID#\"," - "\"name\":\"#SENSORNAME#\"," - "\"stat_t\":\"#MASTERTOPIC##STATETOPIC#\"," - "\"val_tpl\":\"{{value_json.#VALUENAME#}}\"," - "\"ent_cat\":\"diagnostic\"," - "\"ic\":\"mdi:#ICON#\"," - "\"enabled_by_default\":\"false\"" - "}")); - configPayloadTemplate.replace(" ", ""); - configPayloadTemplate.replace(F("#DEVICEID#"), deviceID); - configPayloadTemplate.replace(F("#HOSTNAME#"), hostname); - configPayloadTemplate.replace(F("#VERSION#"), VERSION); - configPayloadTemplate.replace(F("#MASTERTOPIC#"), mqttMasterTopic); - configPayloadTemplate.replace(F("#IP#"), ip_url); - - topic = configTopicTemplate; - topic.replace(F("#COMPONENT#"), F("sensor")); - topic.replace(F("#SENSORID#"), F("WifiSSID")); - - payload = configPayloadTemplate; - payload.replace(F("#SENSORID#"), F("WifiSSID")); - payload.replace(F("#SENSORNAME#"), F("SSID")); - payload.replace(F("#STATETOPIC#"), F("matrixinfo")); - payload.replace(F("#VALUENAME#"), F("wifiSSID")); - payload.replace(F("#ICON#"), F("wifi")); - client.publish(topic.c_str(), payload.c_str(), true); - - // Wifi BSSID - topic = configTopicTemplate; - topic.replace(F("#COMPONENT#"), F("sensor")); - topic.replace(F("#SENSORID#"), F("WifiBSSID")); - - payload = configPayloadTemplate; - payload.replace(F("#SENSORID#"), F("WifiBSSID")); - payload.replace(F("#SENSORNAME#"), F("BSSID")); - payload.replace(F("#STATETOPIC#"), F("matrixinfo")); - payload.replace(F("#VALUENAME#"), F("wifiBSSID")); - payload.replace(F("#ICON#"), F("wifi")); - client.publish(topic.c_str(), payload.c_str(), true); - - // Chip ID - topic = configTopicTemplate; - topic.replace(F("#COMPONENT#"), F("sensor")); - topic.replace(F("#SENSORID#"), F("chipID")); - - payload = configPayloadTemplate; - payload.replace(F("#SENSORID#"), F("chipID")); - payload.replace(F("#SENSORNAME#"), F("Chip ID")); - payload.replace(F("#STATETOPIC#"), F("matrixinfo")); - payload.replace(F("#VALUENAME#"), F("chipID")); - payload.replace(F("#ICON#"), F("developer-board")); - client.publish(topic.c_str(), payload.c_str(), true); - - // LED Matrix on/off + brightness light - configPayloadTemplate = String(F( - "{" - "\"dev\":{" - "\"ids\":\"#DEVICEID#\"," - "\"name\":\"#HOSTNAME#\"," - "\"mdl\":\"PixelIt\"," - "\"mf\":\"PixelIt\"," - "\"sw\":\"#VERSION#\"," - "\"cu\":\"#IP#\"" - "}," - "\"avty_t\":\"#MASTERTOPIC#state\"," - "\"pl_avail\":\"connected\"," - "\"pl_not_avail\":\"disconnected\"," - "\"uniq_id\":\"#DEVICEID##SENSORID#\"," - "\"name\":\"#SENSORNAME#\"," - "\"schema\":\"template\"," - "\"stat_t\":\"#MASTERTOPIC##STATETOPIC#\"," - "\"stat_tpl\":\"{{ \'on\' if value_json.sleepMode is false else \'off\' }}\"," - "\"cmd_t\":\"#MASTERTOPIC##COMMANDTOPIC#\"," - "\"cmd_on_tpl\":\"{\'sleepMode\': false {%- if brightness is defined -%}, \'brightness\': {{ brightness }}{%- endif -%}}\"," - "\"cmd_off_tpl\":\"{\'sleepMode\': true}\"," - "\"bri_tpl\":\"{{ value_json.currentMatrixBrightness }}\"," - "\"icon\":\"mdi:#ICON#\"" - "}")); - configPayloadTemplate.replace(F("#DEVICEID#"), deviceID); - configPayloadTemplate.replace(F("#HOSTNAME#"), hostname); - configPayloadTemplate.replace(F("#VERSION#"), VERSION); - configPayloadTemplate.replace(F("#MASTERTOPIC#"), mqttMasterTopic); - configPayloadTemplate.replace(F("#IP#"), ip_url); - - topic = configTopicTemplate; - topic.replace(F("#COMPONENT#"), F("light")); - topic.replace(F("#SENSORID#"), F("LEDMatrixLight")); - - payload = configPayloadTemplate; - payload.replace(F("#SENSORID#"), F("LEDMatrixLight")); - payload.replace(F("#SENSORNAME#"), F("LED Matrix")); - payload.replace(F("#STATETOPIC#"), F("matrixinfo")); - payload.replace(F("#COMMANDTOPIC#"), F("setScreen")); - payload.replace(F("#ICON#"), F("led-strip")); - client.publish(topic.c_str(), payload.c_str(), true); - - Log(F("MQTTreconnect"), F("MQTT discovery information published")); + Log(F("MQTTreconnect"), F("MQTT discovery information published")); + } } else { @@ -3696,12 +3802,21 @@ void setup() ShowBatteryScreen(); } - // Hostname + // Set unique device ID + deviceID = "PixelIt-"; +#if defined(ESP8266) + deviceID += ESP.getChipId(); +#elif defined(ESP32) + deviceID += uint64ToString(ESP.getEfuseMac()); +#endif + // Set hostname from config + // variable is already validated in LoadConfig() if (hostname.isEmpty()) { - hostname = "PixelIt"; + hostname = deviceID; } WiFi.hostname(hostname); + mqttDeviceTopic = mqttMasterTopic + hostname + "/"; wifiManager.setAPCallback(EnteredHotspotCallback); wifiManager.setMinimumSignalQuality(); @@ -4040,6 +4155,7 @@ void loop() { SetCurrentMatrixBrightness(newBrightness); Log(F("Auto Brightness"), "Lux: " + String(currentLux) + " set brightness to " + String(currentMatrixBrightness)); + matrix->show(); } } } @@ -4093,6 +4209,10 @@ void SendMatrixInfo() if (mqttAktiv == true && client.connected()) { client.publish((mqttMasterTopic + "matrixinfo").c_str(), matrixInfo.c_str(), true); + if (mqttUseDeviceTopic) + { + client.publish((mqttDeviceTopic + "matrixinfo").c_str(), matrixInfo.c_str(), true); + } } // Check if sending via websocket is required if (webSocket.connectedClients() > 0) @@ -4123,6 +4243,10 @@ void SendLDR(bool force) if (mqttAktiv == true && client.connected() && oldGetLuxSensor != luxSensor) { client.publish((mqttMasterTopic + "luxsensor").c_str(), luxSensor.c_str(), true); + if (mqttUseDeviceTopic) + { + client.publish((mqttDeviceTopic + "luxsensor").c_str(), luxSensor.c_str(), true); + } } // Prüfen ob über Websocket versendet werden muss if (webSocket.connectedClients() > 0 && oldGetLuxSensor != luxSensor) @@ -4165,6 +4289,11 @@ void SendSensor(bool force) { client.publish((mqttMasterTopic + "dhtsensor").c_str(), Sensor.c_str(), true); // Legancy client.publish((mqttMasterTopic + "sensor").c_str(), Sensor.c_str(), true); + if (mqttUseDeviceTopic) + { + client.publish((mqttDeviceTopic + "dhtsensor").c_str(), Sensor.c_str(), true); // Legancy + client.publish((mqttDeviceTopic + "sensor").c_str(), Sensor.c_str(), true); + } } // Prüfen ob über Websocket versendet werden muss if (webSocket.connectedClients() > 0 && oldGetSensor != Sensor) From 5078d8eb6e25df5dbee86023bcfc66ef7dd8a120 Mon Sep 17 00:00:00 2001 From: foorschtbar Date: Sun, 12 Nov 2023 19:53:58 +0100 Subject: [PATCH 13/13] update readme --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b7e2682..c018405 100644 --- a/README.md +++ b/README.md @@ -124,8 +124,10 @@ Thanks to these great people for supporting this project. - (o0shojo0o) Adjustments in the WebUI for the new API structure of the UserMap endpoint - (o0shojo0o) Also now in the WebUI Improved check of new firmware through a real version comparison - (o0shojo0o) Added config backup and restore to WebUI [[#319](https://github.com/pixelit-project/PixelIt/issues/319)] -- (o0shojo0o) Added Statistics to WebUI +- (o0shojo0o) Added Statistics to WebUI - (jekader) Added large 8px non-bold clock font [[#320](https://github.com/pixelit-project/PixelIt/pull/320)] +- (foorschtbar) Made HomeAssistant service discovery configurable +- (foorschtbar) Added optional MQTT device topic (`//`) ### 2.4.3 (2023-10-17)