diff --git a/docs/api.md b/docs/api.md index 8e69cd5f..384f845c 100644 --- a/docs/api.md +++ b/docs/api.md @@ -382,7 +382,8 @@ You can adjust each property in the JSON object according to your preferences. I | `HUM` | boolean | Enable or disable the native humidity app (requires reboot). | `true`/`false` | true | | `TEMP` | boolean | Enable or disable the native temperature app (requires reboot). | `true`/`false` | true | | `BAT` | boolean | Enable or disable the native battery app (requires reboot). | `true`/`false` | true | -| `MATP` | boolean | Enable or disable the matrix. Similar to `power` Endpoint but without the animation. | `true`/`false` | true | +| `MATP` | boolean | Enable or disable the matrix. Similar to `power` Endpoint but without the animation. | `true`/`false` | true | +| `VOL` | integer | Allows to set the Volume of the DFplayer (Only for **old** AWTRIX2.0 upgrades ) | 0-30 | true | **Color Values**: Can either be an RGB array (e.g., `[255,0,0]`) or a valid 6-digit hexadecimal color value (e.g., "#FF0000" for red). diff --git a/docs/dev.md b/docs/dev.md index 3d853d63..bd84f669 100644 --- a/docs/dev.md +++ b/docs/dev.md @@ -24,6 +24,8 @@ The JSON object has the following properties: | `hum_offset` | float | Sets the offset for the internal humidity measurement | `0` | | `min_brightness` | integer | Sets minimum brightness level for the Autobrightness control | `2` | | `max_brightness` | integer | Sets maximum brightness level for the Autobrightness control. On high levels, this could result in overheating! | `180` | +| `ldr_gamma` | float | Allows to set the gammacorrection of the brightness control | 3.0 | +| `ldr_factor` | float | This factor is calculated into the raw ldr value wich is 0-1023 | 1.0 | | `min_battery` | integer | Calibrates the minimum battery measurement by the given raw value. You will get that from the stats api | `475` | | `max_battery` | integer | Calibrates the maximum battery measurement by the given raw value. You will get that from the stats api | `665` | | `ha_prefix` | string | Sets the prefix for Homassistant discovery | `homeassistant` | @@ -31,4 +33,5 @@ The JSON object has the following properties: | `stats_interval` | integer | Sets the interval in milliseconds when awtrix should send its stats to HA and MQTT | 10000 | | `debug_mode` | boolean | Enables serial debug outputs. | false | | `dfplayer` | boolean | Enables DFPLayer for Awtrix2_conversation builds. | false | -| `button_callback` | string | http callback url for button presses. | - | \ No newline at end of file +| `button_callback` | string | http callback url for button presses. | - | +| `let_it_snow` | boolean | Let it snow as a global Overlay. | true for christmastime | diff --git a/src/DisplayManager.cpp b/src/DisplayManager.cpp index 4d9cd4b4..b2e2e01e 100644 --- a/src/DisplayManager.cpp +++ b/src/DisplayManager.cpp @@ -621,7 +621,7 @@ bool DisplayManager_::generateCustomPage(const String &name, JsonObject doc, boo { String newIconName = doc["icon"].as(); - if (newIconName.endsWith("=")) + if (newIconName.length()>64) { customApp.jpegDataSize = decode_base64((const unsigned char *)newIconName.c_str(), customApp.jpegDataBuffer); customApp.isGif = false; @@ -901,7 +901,7 @@ bool DisplayManager_::generateNotification(uint8_t source, const char *json) { String iconValue = doc["icon"].as(); - if (iconValue.endsWith("=")) + if (iconValue.length()>64) { newNotification.jpegDataSize = decode_base64((const unsigned char *)iconValue.c_str(), newNotification.jpegDataBuffer); newNotification.isGif = false; @@ -1094,7 +1094,7 @@ void DisplayManager_::setup() ui->setTargetFPS(MATRIX_FPS); ui->setTimePerApp(TIME_PER_APP); ui->setTimePerTransition(TIME_PER_TRANSITION); - ui->setOverlays(overlays, 3); + ui->setOverlays(overlays, 4); ui->setBackgroundEffect(BACKGROUND_EFFECT); setAutoTransition(AUTO_TRANSITION); ui->init(); @@ -1951,6 +1951,7 @@ String DisplayManager_::getSettings() doc["HUM"] = SHOW_HUM; doc["TEMP"] = SHOW_TEMP; doc["BAT"] = SHOW_BAT; + String jsonString; return serializeJson(doc, jsonString), jsonString; } @@ -2001,6 +2002,15 @@ void DisplayManager_::setNewSettings(const char *json) SHOW_HUM = doc.containsKey("HUM") ? doc["HUM"].as() : SHOW_HUM; SHOW_TEMP = doc.containsKey("TEMP") ? doc["TEMP"].as() : SHOW_TEMP; SHOW_BAT = doc.containsKey("BAT") ? doc["BAT"].as() : SHOW_BAT; + + #ifndef ULANZI + if (doc.containsKey("VOL")) + { + DFP_VOLUME = doc["VOL"]; + PeripheryManager.setVolume(DFP_VOLUME); + } + #endif + if (doc.containsKey("CCORRECTION")) { auto colorValue = doc["CCORRECTION"]; @@ -2310,7 +2320,7 @@ void DisplayManager_::processDrawInstructions(int16_t xOffset, int16_t yOffset, { for (int col = 0; col < width; ++col) { - matrix->drawPixel(x + col, y + row, bitmap[bitmapIndex++]); + matrix->drawPixel(x + col + xOffset, y + row + yOffset, bitmap[bitmapIndex++]); } } } diff --git a/src/Globals.cpp b/src/Globals.cpp index b8910ab1..9d99850c 100644 --- a/src/Globals.cpp +++ b/src/Globals.cpp @@ -121,6 +121,16 @@ void loadDevSettings() MAX_BRIGHTNESS = doc["max_brightness"]; } + if (doc.containsKey("ldr_factor")) + { + LDR_FACTOR = doc["ldr_factor"].as(); + } + + if (doc.containsKey("ldr_gamma")) + { + LDR_GAMMA = doc["ldr_gamma"].as(); + } + if (doc.containsKey("hum_offset")) { HUM_OFFSET = doc["hum_offset"]; @@ -156,7 +166,12 @@ void loadDevSettings() DEBUG_MODE = doc["debug_mode"].as(); } - if (doc.containsKey("button_callback")) + if (doc.containsKey("let_it_snow")) + { + SNOW = doc["let_it_snow"].as(); + } + + if (doc.containsKey("button_callback")) { BUTTON_CALLBACK = doc["button_callback"].as(); } @@ -245,8 +260,7 @@ void loadSettings() #endif SOUND_ACTIVE = Settings.getBool("SOUND", true); #ifndef ULANZI - VOLUME_PERCENT = Settings.getUInt("VOL", 50); - VOLUME = map(VOLUME_PERCENT, 0, 100, 0, 30); + DFP_VOLUME = Settings.getUInt("VOL", 20); #endif Settings.end(); uniqueID = getID(); @@ -296,7 +310,7 @@ void saveSettings() #endif Settings.putBool("SOUND", SOUND_ACTIVE); #ifndef ULANZI - Settings.putUInt("VOL", VOLUME_PERCENT); + Settings.putUInt("VOL", DFP_VOLUME); #endif Settings.end(); } @@ -307,7 +321,7 @@ IPAddress gateway; IPAddress subnet; IPAddress primaryDNS; IPAddress secondaryDNS; -const char *VERSION = "0.91"; +const char *VERSION = "0.92"; String MQTT_HOST = ""; uint16_t MQTT_PORT = 1883; @@ -378,8 +392,7 @@ bool SOUND_ACTIVE; String BOOT_SOUND = ""; int TEMP_DECIMAL_PLACES = 0; #ifndef ULANZI -uint8_t VOLUME_PERCENT; -uint8_t VOLUME; +uint8_t DFP_VOLUME; #endif int MATRIX_LAYOUT = 0; bool UPDATE_AVAILABLE = false; @@ -415,4 +428,7 @@ double movementFactor = 0.5; int8_t TRANS_EFFECT = 1; String AUTH_USER = ""; String AUTH_PASS = "awtrix"; -String BUTTON_CALLBACK = ""; \ No newline at end of file +String BUTTON_CALLBACK = ""; +bool SNOW = true; +float LDR_GAMMA = 3.0; +float LDR_FACTOR = 1.0; \ No newline at end of file diff --git a/src/Globals.h b/src/Globals.h index 57b91066..5346b786 100644 --- a/src/Globals.h +++ b/src/Globals.h @@ -99,8 +99,7 @@ extern bool SOUND_ACTIVE; extern String BOOT_SOUND; extern int TEMP_DECIMAL_PLACES; #ifndef ULANZI -extern uint8_t VOLUME_PERCENT; -extern uint8_t VOLUME; +extern uint8_t DFP_VOLUME; #endif extern int MATRIX_LAYOUT; extern bool UPDATE_AVAILABLE; @@ -135,8 +134,11 @@ extern bool MOODLIGHT_MODE; extern double movementFactor; extern uint8_t MIN_BRIGHTNESS; extern uint8_t MAX_BRIGHTNESS; +extern float LDR_GAMMA; +extern float LDR_FACTOR; extern bool DEBUG_MODE; extern String AUTH_USER; extern String AUTH_PASS; extern String BUTTON_CALLBACK; -#endif // Globals_H +extern bool SNOW; +#endif // Globals_H \ No newline at end of file diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index d33cd140..26902d7f 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -215,7 +215,7 @@ String MenuManager_::menutext() break; #ifndef ULANZI case VolumeMenu: - return String(VOLUME_PERCENT) + "%"; + return String(DFP_VOLUME); #endif default: break; @@ -272,10 +272,10 @@ void MenuManager_::rightButton() break; #ifdef awtrix2_upgrade case VolumeMenu: - if ((VOLUME_PERCENT + 1) > 100) - VOLUME_PERCENT = 0; + if ((DFP_VOLUME + 1) > 30) + DFP_VOLUME = 0; else - VOLUME_PERCENT++; + DFP_VOLUME++; #endif default: break; @@ -333,10 +333,10 @@ void MenuManager_::leftButton() break; #ifdef awtrix2_upgrade case VolumeMenu: - if ((VOLUME_PERCENT - 1) < 0) - VOLUME_PERCENT = 100; + if ((DFP_VOLUME - 1) < 0) + DFP_VOLUME = 30; else - VOLUME_PERCENT--; + DFP_VOLUME--; #endif default: break; @@ -492,8 +492,7 @@ void MenuManager_::selectButtonLong() break; #ifdef awtrix2_upgrade case VolumeMenu: - VOLUME = map(VOLUME_PERCENT, 0, 100, 0, 30); - PeripheryManager.setVolume(VOLUME); + PeripheryManager.setVolume(DFP_VOLUME); saveSettings(); break; #endif diff --git a/src/Overlays.cpp b/src/Overlays.cpp index b48ca6af..004aece3 100644 --- a/src/Overlays.cpp +++ b/src/Overlays.cpp @@ -24,15 +24,54 @@ void StatusOverlay(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, GifPl void MenuOverlay(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, GifPlayer *gifPlayer) { - + if (!MenuManager.inMenu) return; - + matrix->fillScreen(0); DisplayManager.setTextColor(0xFFFFFF); DisplayManager.printText(0, 6, utf8ascii(MenuManager.menutext()).c_str(), true, 2); } +CRGB snowLeds[32][8]; +uint8_t updateFrame = 0; + +void SnowOverlay(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, GifPlayer *gifPlayer) +{ + if (!SNOW) + return; + + if (random8() < 20) + { + int randomColumn = random8(32); + snowLeds[randomColumn][0] = CHSV(0, 0, 255); + } + + if (++updateFrame >= 5) + { + for (int i = 0; i < 32; i++) + { + for (int j = 7; j > 0; j--) + { + snowLeds[i][j] = snowLeds[i][j - 1]; + } + snowLeds[i][0] = CRGB::Black; + } + updateFrame = 0; + } + + for (int i = 0; i < 32; i++) + { + for (int j = 0; j < 8; j++) + { + if (snowLeds[i][j]) + { + matrix->drawPixel(i, j, snowLeds[i][j]); + } + } + } +} + void NotifyOverlay(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, GifPlayer *gifPlayer) { // Check if notification flag is set @@ -143,7 +182,7 @@ void NotifyOverlay(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, GifPl iconWidth = 8; if (notifications[0].jpegDataSize > 0) { - DisplayManager.drawJPG(0, 0, notifications[0].jpegDataBuffer, notifications[0].jpegDataSize); + DisplayManager.drawJPG(notifications[0].iconPosition + notifications[0].iconOffset, 0, notifications[0].jpegDataBuffer, notifications[0].jpegDataSize); } else { @@ -363,4 +402,4 @@ void NotifyOverlay(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, GifPl DisplayManager.getInstance().resetTextColor(); } -OverlayCallback overlays[] = {MenuOverlay, NotifyOverlay, StatusOverlay}; \ No newline at end of file +OverlayCallback overlays[] = {MenuOverlay, NotifyOverlay, StatusOverlay, SnowOverlay}; \ No newline at end of file diff --git a/src/Overlays.h b/src/Overlays.h index cc4d95ed..bdd7b1c1 100644 --- a/src/Overlays.h +++ b/src/Overlays.h @@ -60,5 +60,7 @@ void MenuOverlay(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, GifPlay void NotifyOverlay(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, GifPlayer *gifPlayer); +void SnowOverlay(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, GifPlayer *gifPlayer); + extern OverlayCallback overlays[]; #endif \ No newline at end of file diff --git a/src/PeripheryManager.cpp b/src/PeripheryManager.cpp index 1828d6fe..3ee80278 100644 --- a/src/PeripheryManager.cpp +++ b/src/PeripheryManager.cpp @@ -353,7 +353,7 @@ void PeripheryManager_::setup() { dfmp3.begin(); delay(100); - setVolume(VOLUME); + setVolume(DFP_VOLUME); } #endif @@ -442,7 +442,8 @@ void PeripheryManager_::tick() uint16_t ADCVALUE = analogRead(BATTERY_PIN); // Discard values that are totally out of range, especially the first value read after a reboot. // Meaningful values for a Ulanzi are in the range 400..700 - if ((ADCVALUE > 100) && (ADCVALUE < 1000)) { + if ((ADCVALUE > 100) && (ADCVALUE < 1000)) + { BATTERY_PERCENT = max(min((int)map(ADCVALUE, MIN_BATTERY, MAX_BATTERY, 0, 100), 100), 0); BATTERY_RAW = ADCVALUE; SENSORS_STABLE = true; @@ -479,8 +480,13 @@ void PeripheryManager_::tick() CURRENT_TEMP += TEMP_OFFSET; CURRENT_HUM += HUM_OFFSET; } + else + { + SENSORS_STABLE = true; + } } + unsigned long currentMillis_LDR = millis(); if (currentMillis_LDR - previousMillis_LDR >= interval_LDR) { @@ -498,8 +504,8 @@ void PeripheryManager_::tick() CURRENT_LUX = (roundf(photocell.getSmoothedLux() * 1000) / 1000); if (AUTO_BRIGHTNESS && !MATRIX_OFF) { - brightnessPercent = sampleAverage / 1023.0 * 100.0; - brightnessPercent = (brightnessPercent * brightnessPercent * brightnessPercent) / (100.0 * 100.0); // apply gamma correction (gamma = 3) + brightnessPercent = (sampleAverage * LDR_FACTOR) / 1023.0 * 100.0; + brightnessPercent = pow(brightnessPercent, LDR_GAMMA) / pow(100.0, LDR_GAMMA - 1); BRIGHTNESS = map(brightnessPercent, 0, 100, MIN_BRIGHTNESS, MAX_BRIGHTNESS); DisplayManager.setBrightness(BRIGHTNESS); } @@ -512,10 +518,13 @@ unsigned long long PeripheryManager_::readUptime() static unsigned long long totalElapsed = 0; unsigned long currentTime = millis(); - if (currentTime < lastTime) { + if (currentTime < lastTime) + { // millis() overflow totalElapsed += 4294967295UL - lastTime + currentTime + 1; - } else { + } + else + { totalElapsed += currentTime - lastTime; } lastTime = currentTime; @@ -524,7 +533,6 @@ unsigned long long PeripheryManager_::readUptime() return uptimeSeconds; } - void PeripheryManager_::r2d2(const char *msg) { #ifdef ULANZI diff --git a/src/effects.cpp b/src/effects.cpp index 1ebad5af..673c1c97 100644 --- a/src/effects.cpp +++ b/src/effects.cpp @@ -27,7 +27,6 @@ void Pacifica(FastLED_NeoMatrix *matrix, int16_t x, int16_t y, EffectSettings *s void TheaterChase(FastLED_NeoMatrix *matrix, int16_t x, int16_t y, EffectSettings *settings) { - static uint16_t j = 0; static uint32_t lastUpdate = 0; if (millis() - lastUpdate > 100 - settings->speed * 10) @@ -250,6 +249,8 @@ void TwinklingStars(FastLED_NeoMatrix *matrix, int16_t x, int16_t y, EffectSetti } } + + // ######## LookingEyes ############ int blinkIndex[] = {1, 2, 3, 4, 3, 2, 1};