diff --git a/docs/api.md b/docs/api.md index 24ef510..9b27a52 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1,26 +1,42 @@ # MQTT / HTTP API - - + ## Status In MQTT awtrix send its stats every 10s to `[PREFIX]/stats` With HTTP, make GET request to `http://[IP]/api/stats` - - -## Update -Awtrix searches for an update every 1 Hour. If a new one is found it will be published to HA and in the stats. -You can start the update with update button in HA or: - -| Topic | URL | Payload/Body | HTTP Header | HTTP method | -| --- | --- | --- | --- | --- | -| `[PREFIX]/doupdate` |`http://[IP]/api/doupdate` | JSON | empty payload/body | POST | + +## Turn display on or off + +| Topic | URL | Payload/Body | HTTP method | +| --- | --- | --- | --- | +| `[PREFIX]/power` | `http://[IP]/api/power` | `{"state":value}` | POST | + +Valid values are: +- `0` => off +- `1` => on + + +## Colored indicators + +A colored indicator is like a small notification sign wich will be shown on the upper right or lower right corner. + +| Topic | URL | Payload/Body | HTTP method | +| --- | --- | --- | --- | +| `[PREFIX]/indicator1` | `http://[IP]/api/indicator1` | `{"color":[255,0,0]}` | POST | +| `[PREFIX]/indicator2` | `http://[IP]/api/indicator2` | `{"color":[0,255,0]}` | POST | + +Instead of a RGB array you can also sent HEX color strings like `{"color":"#32a852"}` +Send the color black `{"color":[0,0,0]}` or `{"color":"0"}` to hide the indicators. +Optionally you can make the indicator blinking by adding the key `"blink":true/false`. + ## Custom Apps and Notifications With AWTRIX Light, you can create custom apps or notifications to display your own text and icons. -With MQTT simply send a JSON object to the topic `[PREFIX]/custom/[page]` where [page] is a the name of your page (without spaces). -With the [HTTP API](api?id=add-custom-app) you have to set the appname in the request header (`name = Appname`) - +With MQTT simply send a JSON object to the topic `[PREFIX]/custom/[app]` where [app] is a the name of your app (without spaces). +With the HTTP API you have to set the appname in the request header (`name = [appname]`) +You can also send a one-time notification with the same JSON format. Simply send your JSON object to `[PREFIX]/notify` or `http://[IP]/api/notify`. + | Topic | URL | Payload/Body | Query parameters | HTTP method | | --- | --- | --- | --- | --- | | `[PREFIX]/custom/[appname]` |`http://[IP]/api/custom` | JSON | name = [appname] | POST | @@ -43,14 +59,14 @@ The JSON object has the following properties: | `sound` | string | The filename of your RTTTL ringtone file (without extension). | | | `pushIcon` | number | 0 = Icon doesn't move. 1 = Icon moves with text and will not appear again. 2 = Icon moves with text but appears again when the text starts to scroll again. | 0 | | `bar` | array of integers | draws a bargraph. Without icon maximum 16 values, with icon 11 values | | -| `textCase` | integer | Changes teh Uppercase setting. 0=global setting, 1=forces uppercase; 2=shows what is sent. | 0 | +| `textCase` | integer | Changes the Uppercase setting. 0=global setting, 1=forces uppercase; 2=shows as it sent. | 0 | All keys are optional, so you can send just the properties you want to use. To update a custom page, simply send a modified JSON object to the same topic. The display will be updated immediately. -You can also send a one-time notification with the same JSON format. Simply send your JSON object to "awtrixlight/notify". + ### Example @@ -222,7 +238,7 @@ The JSON object has the following properties: Each value is optional, so you can set a timer for just minutes, or any combination of hours, minutes, and seconds. If you only want to start a timer in some minutes, just send the minutes. -## Example +#### Example Here's an example JSON object to start a timer for 1 hour, 30 minutes, and 10 seconds, with the sound "friends": @@ -234,4 +250,11 @@ Here's an example JSON object to start a timer for 1 hour, 30 minutes, and 10 se "sound": "friends" } ``` - + +## Update +Awtrix searches for an update every 1 Hour. If a new one is found it will be published to HA and in the stats. +You can start the update with update button in HA or: + +| Topic | URL | Payload/Body | HTTP Header | HTTP method | +| --- | --- | --- | --- | --- | +| `[PREFIX]/doupdate` |`http://[IP]/api/doupdate` | JSON | empty payload/body | POST | \ No newline at end of file diff --git a/docs/dev.md b/docs/dev.md index af99160..cd611c2 100644 --- a/docs/dev.md +++ b/docs/dev.md @@ -12,5 +12,6 @@ The JSON object has the following properties: | Key | Type | Description | Default | | --- | ---- | ----------- | ------- | | `bootsound` | string | Uses a custom melodie while booting | | -| `uppercase` | boolean | Print every character in uppercase | true | -| `temp_dec_places` | int | Number of decimal places for temperature measurements | 0 | +| `uppercase` | boolean | Print every character in uppercase | `true` | +| `temp_dec_places` | int | Number of decimal places for temperature measurements | `0` | +| `color_correction` | array of int | Sets the colorcorrection of the matrix | `[255,255,255]` | \ No newline at end of file diff --git a/lib/MatrixUI/MatrixDisplayUi.cpp b/lib/MatrixUI/MatrixDisplayUi.cpp index ba6a9b0..f5f6db4 100644 --- a/lib/MatrixUI/MatrixDisplayUi.cpp +++ b/lib/MatrixUI/MatrixDisplayUi.cpp @@ -30,8 +30,8 @@ #include "MatrixDisplayUi.h" #include "Fonts/AwtrixFont.h" - GifPlayer gif1; - GifPlayer gif2; +GifPlayer gif1; +GifPlayer gif2; MatrixDisplayUi::MatrixDisplayUi(FastLED_NeoMatrix *matrix) { @@ -223,12 +223,44 @@ void MatrixDisplayUi::tick() } this->matrix->clear(); + if (this->AppCount > 0) this->drawApp(); this->drawOverlays(); + this->drawIndicators(); this->matrix->show(); } +void MatrixDisplayUi::drawIndicators() +{ + if (indicator1State && !indicator1Blink) + { + matrix->drawPixel(31, 0, indicator1Color); + matrix->drawPixel(30, 0, indicator1Color); + matrix->drawPixel(31, 1, indicator1Color); + } + if (indicator2State && !indicator2Blink) + { + matrix->drawPixel(31, 7, indicator2Color); + matrix->drawPixel(31, 6, indicator2Color); + matrix->drawPixel(30, 7, indicator2Color); + } + + if (indicator1State && indicator1Blink && (millis() % 1000) < 500) + { + matrix->drawPixel(31, 0, indicator1Color); + matrix->drawPixel(30, 0, indicator1Color); + matrix->drawPixel(31, 1, indicator1Color); + } + + if (indicator2State && indicator2Blink && (millis() % 1000) < 500) + { + matrix->drawPixel(31, 7, indicator2Color); + matrix->drawPixel(31, 6, indicator2Color); + matrix->drawPixel(30, 7, indicator2Color); + } +} + void MatrixDisplayUi::drawApp() { switch (this->state.appState) @@ -293,3 +325,33 @@ uint8_t MatrixDisplayUi::getnextAppNumber() return this->nextAppNumber; return (this->state.currentApp + this->AppCount + this->state.appTransitionDirection) % this->AppCount; } + +void MatrixDisplayUi::setIndicator1Color(uint16_t color) +{ + this->indicator1Color = color; +} + +void MatrixDisplayUi::setIndicator1State(bool state) +{ + this->indicator1State = state; +} + +void MatrixDisplayUi::setIndicator2Color(uint16_t color) +{ + this->indicator2Color = color; +} + +void MatrixDisplayUi::setIndicator2State(bool state) +{ + this->indicator2State = state; +} + +void MatrixDisplayUi::setIndicator1Blink(bool blink) +{ + this->indicator1Blink = blink; +} + +void MatrixDisplayUi::setIndicator2Blink(bool blink) +{ + this->indicator2Blink = blink; +} \ No newline at end of file diff --git a/lib/MatrixUI/MatrixDisplayUi.h b/lib/MatrixUI/MatrixDisplayUi.h index 5ef0e4c..76c6d95 100644 --- a/lib/MatrixUI/MatrixDisplayUi.h +++ b/lib/MatrixUI/MatrixDisplayUi.h @@ -77,7 +77,6 @@ class MatrixDisplayUi private: FastLED_NeoMatrix *matrix; - // Values for the Apps AnimationDirection appAnimationDirection = SLIDE_DOWN; int8_t lastTransitionDirection = 1; @@ -102,6 +101,14 @@ private: // Bookeeping for update uint8_t updateInterval = 33; + uint16_t indicator1Color = 63488; + uint16_t indicator2Color = 31; + + bool indicator1State = false; + bool indicator2State = false; + bool indicator1Blink = false; + bool indicator2Blink = false; + uint8_t getnextAppNumber(); void drawApp(); void drawOverlays(); @@ -148,6 +155,15 @@ public: */ void setTimePerTransition(uint16_t time); + void setIndicator1Color(uint16_t color); + void setIndicator1State(bool state); + void setIndicator2Color(uint16_t color); + void setIndicator2State(bool state); + + void setIndicator1Blink(bool Blink); + void setIndicator2Blink(bool Blink); + + void drawIndicators(); // Customize indicator position and style // App settings diff --git a/src/Dictionary.cpp b/src/Dictionary.cpp index 721bca3..20d879e 100644 --- a/src/Dictionary.cpp +++ b/src/Dictionary.cpp @@ -17,6 +17,15 @@ const char HAmodel[] PROGMEM = {"AWTRIX Light"}; const char HAmatID[] PROGMEM = {"%s_mat"}; const char HAmatIcon[] PROGMEM = {"mdi:lightbulb"}; const char HAmatName[] PROGMEM = {"Matrix"}; + +const char HAi1ID[] PROGMEM = {"%s_ind1"}; +const char HAi1Icon[] PROGMEM = {"mdi:arrow-top-right-thick"}; +const char HAi1Name[] PROGMEM = {"Indicator 1"}; + +const char HAi2ID[] PROGMEM = {"%s_ind2"}; +const char HAi2Icon[] PROGMEM = {"mdi:arrow-bottom-right-thick"}; +const char HAi2Name[] PROGMEM = {"Indicator 2"}; + const char HAbriID[] PROGMEM = {"%s_bri"}; const char HAbriIcon[] PROGMEM = {"mdi:brightness-auto"}; const char HAbriName[] PROGMEM = {"Brightness mode"}; @@ -74,12 +83,10 @@ const char HAupdateName[] PROGMEM = {"Update"}; const char HAupdateClass[] PROGMEM = {"update"}; const char HAupdateIcon[] PROGMEM = {"mdi:update"}; - const char HAdoUpID[] PROGMEM = {"%s_doupd"}; const char HAdoUpName[] PROGMEM = {"Start Update"}; const char HAdoUpIcon[] PROGMEM = {"mdi:update"}; - const char HAsigID[] PROGMEM = {"%s_sig"}; const char HAsigIcon[] PROGMEM = {"mdi:sun-wireless"}; const char HAsigName[] PROGMEM = {"WiFi strength"}; diff --git a/src/Dictionary.h b/src/Dictionary.h index 1b44a63..39aca56 100644 --- a/src/Dictionary.h +++ b/src/Dictionary.h @@ -17,6 +17,15 @@ extern const char HAmodel[]; extern const char HAmatID[]; extern const char HAmatIcon[]; extern const char HAmatName[]; + +extern const char HAi1ID[]; +extern const char HAi1Icon[]; +extern const char HAi1Name[]; + +extern const char HAi2ID[]; +extern const char HAi2Icon[]; +extern const char HAi2Name[]; + extern const char HAbriID[]; extern const char HAbriIcon[]; extern const char HAbriName[]; diff --git a/src/DisplayManager.cpp b/src/DisplayManager.cpp index 2ce1518..a2a019b 100644 --- a/src/DisplayManager.cpp +++ b/src/DisplayManager.cpp @@ -37,6 +37,8 @@ CRGB leds[MATRIX_WIDTH * MATRIX_HEIGHT]; FastLED_NeoMatrix *matrix = new FastLED_NeoMatrix(leds, 8, 8, 4, 1, NEO_MATRIX_TOP + NEO_MATRIX_LEFT + NEO_MATRIX_ROWS + NEO_MATRIX_PROGRESSIVE); MatrixDisplayUi *ui = new MatrixDisplayUi(matrix); +uint8_t lastBrightness; + DisplayManager_ &DisplayManager_::getInstance() { static DisplayManager_ instance; @@ -54,6 +56,11 @@ void DisplayManager_::setBrightness(uint8_t bri) else { matrix->setBrightness(bri); + if (GAMMA > 0) + { + Serial.println(GAMMA); + napplyGamma_video(&leds[256], 256, GAMMA); + } } } @@ -140,6 +147,7 @@ bool jpg_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap) void DisplayManager_::printText(int16_t x, int16_t y, const char *text, bool centered, byte textCase) { + if (centered) { uint16_t textWidth = getTextWidth(text, textCase); @@ -533,9 +541,12 @@ void DisplayManager_::setup() TJpgDec.setCallback(jpg_output); TJpgDec.setJpgScale(1); - FastLED.addLeds(leds, MATRIX_WIDTH * MATRIX_HEIGHT).setTemperature(OvercastSky); + FastLED.addLeds(leds, MATRIX_WIDTH * MATRIX_HEIGHT); setMatrixLayout(MATRIX_LAYOUT); - + if (COLOR_CORRECTION) + { + FastLED.setCorrection(COLOR_CORRECTION); + } gif.setMatrix(matrix); ui->setAppAnimation(SLIDE_DOWN); ui->setTimePerApp(TIME_PER_APP); @@ -555,6 +566,7 @@ void DisplayManager_::tick() else { + ui->update(); if (ui->getUiState()->appState == IN_TRANSITION && !appIsSwitching) @@ -800,10 +812,12 @@ std::pair getNativeAppByName(const String &appName) { return std::make_pair("hum", HumApp); } +#ifdef ULANZI else if (appName == "bat") { return std::make_pair("bat", BatApp); } +#endif return std::make_pair("", nullptr); } @@ -941,3 +955,145 @@ String DisplayManager_::getAppsAsJson() serializeJson(appsObject, json); return json; } + +void DisplayManager_::powerStateParse(const char *json) +{ + DynamicJsonDocument doc(128); + DeserializationError error = deserializeJson(doc, json); + if (error) + return; + if (doc.containsKey("state")) + { + bool state = doc["state"].as(); + setPower(state); + } +} + +void DisplayManager_::setPower(bool state) +{ + if (state) + { + MATRIX_OFF = false; + setBrightness(lastBrightness); + } + else + { + MATRIX_OFF = true; + lastBrightness = BRIGHTNESS; + setBrightness(0); + } +} + +void DisplayManager_::setIndicator1Color(uint16_t color) +{ + ui->setIndicator1Color(color); +} + +void DisplayManager_::setIndicator1State(bool state) +{ + ui->setIndicator1State(state); +} + +void DisplayManager_::setIndicator2Color(uint16_t color) +{ + ui->setIndicator2Color(color); +} + +void DisplayManager_::setIndicator2State(bool state) +{ + ui->setIndicator2State(state); +} + +void DisplayManager_::indicatorParser(uint8_t indicator, const char *json) +{ + DynamicJsonDocument doc(128); + DeserializationError error = deserializeJson(doc, json); + if (error) + return; + if (doc.containsKey("color")) + { + auto color = doc["color"]; + if (color.is()) + { + uint16_t col = hexToRgb565(color.as()); + if (col > 0) + { + if (indicator == 1) + { + ui->setIndicator1State(true); + ui->setIndicator1Color(col); + } + else + { + ui->setIndicator2State(true); + ui->setIndicator2Color(col); + } + } + else + { + if (indicator == 1) + { + ui->setIndicator1State(false); + } + else + { + ui->setIndicator2State(false); + } + } + } + else if (color.is() && color.size() == 3) + { + uint8_t r = color[0]; + uint8_t g = color[1]; + uint8_t b = color[2]; + + if (r == 0 && g == 0 && b == 0) + { + if (indicator == 1) + { + ui->setIndicator1State(false); + } + else + { + ui->setIndicator2State(false); + } + } + else + { + if (indicator == 1) + { + ui->setIndicator1State(true); + ui->setIndicator1Color((r << 11) | (g << 5) | b); + } + else + { + ui->setIndicator2State(true); + ui->setIndicator2Color((r << 11) | (g << 5) | b); + } + } + } + } + + if (doc.containsKey("blink")) + { + if (indicator == 1) + { + ui->setIndicator1Blink(doc["blink"].as()); + } + else + { + ui->setIndicator2Blink(doc["blink"].as()); + } + } + else + { + if (indicator == 1) + { + ui->setIndicator1Blink(false); + } + else + { + ui->setIndicator2Blink(false); + } + } +} \ No newline at end of file diff --git a/src/DisplayManager.h b/src/DisplayManager.h index e7da06e..fb6081c 100644 --- a/src/DisplayManager.h +++ b/src/DisplayManager.h @@ -51,11 +51,10 @@ public: void MatrixState(bool); void generateNotification(const char *json); void generateCustomPage(const String &name, const char *json); - void printText(int16_t x, int16_t y, const char *text, bool centered, byte textCase); + void printText(int16_t x, int16_t y, const char *text, bool centered, byte textCase); bool setAutoTransition(bool active); void switchToApp(const char *json); void setNewSettings(const char *json); - void drawGIF(uint16_t x, uint16_t y, fs::File gifFile); void drawJPG(uint16_t x, uint16_t y, fs::File jpgFile); void drawProgressBar(int cur, int total); void drawMenuIndicator(int cur, int total, uint16_t color); @@ -66,6 +65,13 @@ public: void setAppTime(uint16_t duration); String getAppsAsJson(); String getStat(); + void setPower(bool state); + void powerStateParse(const char *json); + void setIndicator1Color(uint16_t color); + void setIndicator1State(bool state); + void setIndicator2Color(uint16_t color); + void setIndicator2State(bool state); + void indicatorParser(uint8_t indicator, const char *json); }; extern DisplayManager_ &DisplayManager; diff --git a/src/Functions.h b/src/Functions.h index d82df65..a0dfe6e 100644 --- a/src/Functions.h +++ b/src/Functions.h @@ -8,6 +8,38 @@ std::map CharMap = { {32, 2}, {33, 2}, {34, 4}, {35, 4}, {36, 4}, {37, 4}, {38, 4}, {39, 2}, {40, 3}, {41, 3}, {42, 4}, {43, 4}, {44, 3}, {45, 4}, {46, 2}, {47, 4}, {48, 4}, {49, 4}, {50, 4}, {51, 4}, {52, 4}, {53, 4}, {54, 4}, {55, 4}, {56, 4}, {57, 4}, {58, 2}, {59, 3}, {60, 4}, {61, 4}, {62, 4}, {63, 4}, {64, 4}, {65, 4}, {66, 4}, {67, 4}, {68, 4}, {69, 4}, {70, 4}, {71, 4}, {72, 4}, {73, 2}, {74, 4}, {75, 4}, {76, 4}, {77, 6}, {78, 5}, {79, 4}, {80, 4}, {81, 5}, {82, 4}, {83, 4}, {84, 4}, {85, 4}, {86, 4}, {87, 6}, {88, 4}, {89, 4}, {90, 4}, {91, 4}, {92, 4}, {93, 4}, {94, 4}, {95, 4}, {96, 3}, {97, 4}, {98, 4}, {99, 4}, {100, 4}, {101, 4}, {102, 4}, {103, 4}, {104, 4}, {105, 2}, {106, 4}, {107, 4}, {108, 4}, {109, 4}, {110, 4}, {111, 4}, {112, 4}, {113, 4}, {114, 4}, {115, 4}, {116, 4}, {117, 4}, {118, 4}, {119, 4}, {120, 4}, {121, 4}, {122, 4}, {123, 4}, {124, 2}, {125, 4}, {126, 4}, {161, 2}, {162, 4}, {163, 4}, {164, 4}, {165, 4}, {166, 2}, {167, 4}, {168, 4}, {169, 4}, {170, 4}, {171, 3}, {172, 4}, {173, 3}, {174, 4}, {175, 4}, {176, 4}, {177, 4}, {178, 4}, {179, 4}, {180, 3}, {181, 4}, {182, 4}, {183, 4}, {184, 4}, {185, 2}, {186, 4}, {187, 3}, {188, 4}, {189, 4}, {190, 4}, {191, 4}, {192, 4}, {193, 4}, {194, 4}, {195, 4}, {196, 4}, {197, 4}, {198, 4}, {199, 4}, {200, 4}, {201, 4}, {202, 4}, {203, 4}, {204, 4}, {205, 4}, {206, 4}, {207, 4}, {208, 4}, {209, 4}, {210, 4}, {211, 4}, {212, 4}, {213, 4}, {214, 4}, {215, 4}, {216, 4}, {217, 4}, {218, 4}, {219, 4}, {220, 4}, {221, 4}, {222, 4}, {223, 4}, {224, 4}, {225, 4}, {226, 4}, {227, 4}, {228, 4}, {229, 4}, {230, 4}, {231, 4}, {232, 4}, {233, 4}, {234, 4}, {235, 4}, {236, 3}, {237, 3}, {238, 4}, {239, 4}, {240, 4}, {241, 4}, {242, 4}, {243, 4}, {244, 4}, {245, 4}, {246, 4}, {247, 4}, {248, 4}, {249, 4}, {250, 4}, {251, 4}, {252, 4}, {253, 4}, {254, 4}, {255, 4}, {285, 2}, {338, 4}, {339, 4}, {352, 4}, {353, 4}, {376, 4}, {381, 4}, {382, 4}, {3748, 2}, {5024, 2}, {8226, 2}, {8230, 4}, {8364, 4}, {65533, 4}}; +//--------------------------------------------------------------- +// This is the gamma lookup for mapping 255 brightness levels +// The lookup table would be similar but have slightly shifted +// numbers for different gammas (gamma 2.0, 2.2, 2.5, etc.) +const uint8_t PROGMEM gamma8[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, + 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, + 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, + 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25, + 25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36, + 37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, + 51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, + 69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89, + 90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114, + 115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142, + 144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175, + 177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213, + 215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 }; + + + +CRGB applyGammaCorrection(const CRGB& color) { + CRGB correctedColor; + correctedColor.r = pgm_read_byte(&gamma8[color.r]); + correctedColor.g = pgm_read_byte(&gamma8[color.g]); + correctedColor.b = pgm_read_byte(&gamma8[color.b]); + return correctedColor; +} + uint32_t hsvToRgb(uint8_t h, uint8_t s, uint8_t v) { CHSV hsv(h, s, v); diff --git a/src/Globals.cpp b/src/Globals.cpp index 938a373..b600bc0 100644 --- a/src/Globals.cpp +++ b/src/Globals.cpp @@ -2,6 +2,7 @@ #include "Preferences.h" #include #include + #include Preferences Settings; @@ -66,6 +67,22 @@ void loadDevSettings() TEMP_DECIMAL_PLACES = doc["temp_dec_places"].as(); } + if (doc.containsKey("gamma")) + { + GAMMA = doc["gamma"].as(); + } + + if (doc.containsKey("color_correction")) + { + auto correction = doc["color_correction"]; + if (correction.is() && correction.size() == 3) + { + uint8_t r = correction[0]; + uint8_t g = correction[1]; + uint8_t b = correction[2]; + COLOR_CORRECTION.setRGB(r, g, b); + } + } file.close(); } } @@ -139,7 +156,7 @@ IPAddress gateway; IPAddress subnet; IPAddress primaryDNS; IPAddress secondaryDNS; -const char *VERSION = "0.48"; +const char *VERSION = "0.49"; String MQTT_HOST = ""; uint16_t MQTT_PORT = 1883; String MQTT_USER; @@ -210,4 +227,6 @@ uint8_t VOLUME; #endif int MATRIX_LAYOUT; bool UPDATE_AVAILABLE = false; -long RECEIVED_MESSAGES; \ No newline at end of file +long RECEIVED_MESSAGES; +CRGB COLOR_CORRECTION; +float GAMMA = 0; \ No newline at end of file diff --git a/src/Globals.h b/src/Globals.h index 5a4985c..9ecc722 100644 --- a/src/Globals.h +++ b/src/Globals.h @@ -1,6 +1,7 @@ #ifndef GLOBALS_H #define GLOBALS_H #include +#include extern const char *uniqueID; extern const char *VERSION; @@ -76,6 +77,8 @@ extern uint8_t VOLUME; extern int MATRIX_LAYOUT; extern bool UPDATE_AVAILABLE; extern long RECEIVED_MESSAGES; +extern CRGB COLOR_CORRECTION; +extern float GAMMA; void loadSettings(); void saveSettings(); #endif // Globals_H \ No newline at end of file diff --git a/src/MQTTManager.cpp b/src/MQTTManager.cpp index 1524508..71789a4 100644 --- a/src/MQTTManager.cpp +++ b/src/MQTTManager.cpp @@ -10,14 +10,15 @@ #include "UpdateManager.h" WiFiClient espClient; -uint8_t lastBrightness; HADevice device; -HAMqtt mqtt(espClient, device, 22); +HAMqtt mqtt(espClient, device, 25); unsigned long reconnectTimer = 0; const unsigned long reconnectInterval = 30000; // 30 Sekunden HALight *Matrix = nullptr; +HALight *Indikator1 = nullptr; +HALight *Indikator2 = nullptr; HASelect *BriMode = nullptr; HAButton *dismiss = nullptr; HAButton *nextApp = nullptr; @@ -101,25 +102,36 @@ void onSelectCommand(int8_t index, HASelect *sender) void onRGBColorCommand(HALight::RGBColor color, HALight *sender) { - TEXTCOLOR_565 = ((color.red & 0x1F) << 11) | ((color.green & 0x3F) << 5) | (color.blue & 0x1F); - saveSettings(); + if (sender == Matrix) + { + TEXTCOLOR_565 = ((color.red & 0x1F) << 11) | ((color.green & 0x3F) << 5) | (color.blue & 0x1F); + saveSettings(); + } + else if (sender == Indikator1) + { + DisplayManager.setIndicator1Color(((color.red & 0x1F) << 11) | ((color.green & 0x3F) << 5) | (color.blue & 0x1F)); + } + else if (sender == Indikator2) + { + DisplayManager.setIndicator2Color(((color.red & 0x1F) << 11) | ((color.green & 0x3F) << 5) | (color.blue & 0x1F)); + } sender->setRGBColor(color); // report color back to the Home Assistant } void onStateCommand(bool state, HALight *sender) { - if (state) + if (sender == Matrix) { - MATRIX_OFF = false; - DisplayManager.setBrightness(lastBrightness); + DisplayManager.setPower(state); } - else + else if (sender == Indikator1) { - MATRIX_OFF = true; - lastBrightness = BRIGHTNESS; - DisplayManager.setBrightness(0); + DisplayManager.setIndicator1State(state); + } + else if (sender == Indikator2) + { + DisplayManager.setIndicator2State(state); } - sender->setState(state); } @@ -129,7 +141,6 @@ void onBrightnessCommand(uint8_t brightness, HALight *sender) if (AUTO_BRIGHTNESS) return; BRIGHTNESS = brightness; - lastBrightness = brightness; saveSettings(); DisplayManager.setBrightness(brightness); } @@ -208,7 +219,24 @@ void onMqttMessage(const char *topic, const uint8_t *payload, uint16_t length) delete[] payloadCopy; return; } - + if (strTopic.equals(MQTT_PREFIX + "/power")) + { + DisplayManager.powerStateParse(payloadCopy); + delete[] payloadCopy; + return; + } + if (strTopic.equals(MQTT_PREFIX + "/indicator1")) + { + DisplayManager.indicatorParser(1, payloadCopy); + delete[] payloadCopy; + return; + } + if (strTopic.equals(MQTT_PREFIX + "/indicator2")) + { + DisplayManager.indicatorParser(2, payloadCopy); + delete[] payloadCopy; + return; + } else if (strTopic.startsWith(MQTT_PREFIX + "/custom")) { String topic_str = topic; @@ -239,7 +267,10 @@ void onMqttConnected() "/nextapp", "/doupdate", "/nextapp", - "/apps"}; + "/apps", + "/power", + "/indicator1", + "/indicator2"}; for (const char *topic : topics) { String fullTopic = prefix + topic; @@ -265,7 +296,7 @@ void connect() } } -char matID[40], briID[40]; +char matID[40], ind1ID[40], ind2ID[40], briID[40]; char btnAID[40], btnBID[40], btnCID[40], appID[40], tempID[40], humID[40], luxID[40], verID[40], ramID[40], upID[40], sigID[40], btnLID[40], btnMID[40], btnRID[40], transID[40], updateID[40], doUpdateID[40]; #ifdef ULANZI char batID[40]; @@ -273,7 +304,6 @@ char batID[40]; void MQTTManager_::setup() { - if (HA_DISCOVERY) { Serial.println(F("Starting Homeassistant discorvery")); @@ -304,6 +334,20 @@ void MQTTManager_::setup() Matrix->setCurrentState(true); Matrix->setBRIGHTNESS(BRIGHTNESS); + sprintf(ind1ID, HAi1ID, macStr); + Indikator1 = new HALight(ind1ID, HALight::RGBFeature); + Indikator1->setIcon(HAi1Icon); + Indikator1->setName(HAi1Name); + Indikator1->onStateCommand(onStateCommand); + Indikator1->onRGBColorCommand(onRGBColorCommand); + + sprintf(ind2ID, HAi2ID, macStr); + Indikator2 = new HALight(ind2ID, HALight::RGBFeature); + Indikator2->setIcon(HAi2Icon); + Indikator2->setName(HAi2Name); + Indikator2->onStateCommand(onStateCommand); + Indikator2->onRGBColorCommand(onRGBColorCommand); + HALight::RGBColor color; color.red = (TEXTCOLOR_565 >> 11) << 3; color.green = ((TEXTCOLOR_565 >> 5) & 0x3F) << 2; @@ -368,8 +412,8 @@ void MQTTManager_::setup() humidity->setName(HAhumName); humidity->setDeviceClass(HAhumClass); humidity->setUnitOfMeasurement(HAhumUnit); -#ifdef ULANZI +#ifdef ULANZI sprintf(batID, HAbatID, macStr); battery = new HASensor(batID); battery->setIcon(HAbatIcon); diff --git a/src/PeripheryManager.cpp b/src/PeripheryManager.cpp index 7e397b3..7153e8b 100644 --- a/src/PeripheryManager.cpp +++ b/src/PeripheryManager.cpp @@ -96,7 +96,6 @@ void left_button_pressed() #ifndef ULANZI PeripheryManager.playFromFile(DFMINI_MP3_CLICK); #endif - DisplayManager.leftButton(); MenuManager.leftButton(); } @@ -106,7 +105,6 @@ void right_button_pressed() #ifndef ULANZI PeripheryManager.playFromFile(DFMINI_MP3_CLICK); #endif - DisplayManager.rightButton(); MenuManager.rightButton(); } diff --git a/src/ServerManager.cpp b/src/ServerManager.cpp index 2e4db3e..94e4cf7 100644 --- a/src/ServerManager.cpp +++ b/src/ServerManager.cpp @@ -99,9 +99,15 @@ void ServerManager_::setup() { DisplayManager.generateCustomPage(mws.webserver->arg("name"),mws.webserver->arg("plain").c_str()); mws.webserver->send(200,"OK"); }); mws.addHandler("/api/stats", HTTP_GET, []() { mws.webserver->sendContent(DisplayManager.getStat()); }); + mws.addHandler("/api/indicator1", HTTP_POST, []() + { DisplayManager.indicatorParser(1,mws.webserver->arg("plain").c_str()); mws.webserver->send(200,"OK"); }); + mws.addHandler("/api/indicator2", HTTP_POST, []() + { DisplayManager.indicatorParser(2,mws.webserver->arg("plain").c_str()); mws.webserver->send(200,"OK"); }); mws.addHandler("/api/doupdate", HTTP_POST, []() { if (UPDATE_AVAILABLE) UpdateManager.updateFirmware(); mws.webserver->send(200,"OK"); }); + mws.addHandler("/api/power", HTTP_POST, []() + { DisplayManager.powerStateParse(mws.webserver->arg("plain").c_str()); mws.webserver->send(200,"OK"); }); Serial.println("Webserver loaded"); } mws.addHandler("/version", HTTP_GET, versionHandler); diff --git a/src/main.cpp b/src/main.cpp index 5c42490..b2b40da 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -94,7 +94,6 @@ void setup() delay(200); DisplayManager.setBrightness(BRIGHTNESS); - DisplayManager.clearMatrix(); } void loop()