diff --git a/README.md b/README.md index 97a9970..056df94 100644 --- a/README.md +++ b/README.md @@ -16,11 +16,12 @@ ![Discord](https://img.shields.io/discord/546407049148366859?label=Discord&style=flat-square) [![Compile](https://github.com/Blueforcer/awtrix-light/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/Blueforcer/awtrix-light/actions/workflows/main.yml) + + Watch the video + + -![GIF-230324_161917](https://user-images.githubusercontent.com/31169771/227567565-3780ee83-1158-4371-9390-fd03a7873496.gif) - - -AWTRIX Light is an open‑source custom firmware for the [Ulanzi Smart Pixel clock TC001](https://www.ulanzi.com/products/ulanzi-pixel-smart-clock-2882) +AWTRIX Light is a open‑source custom firmware for the [Ulanzi Smart Pixel clock TC001](https://www.ulanzi.com/products/ulanzi-pixel-smart-clock-2882) AWL meant to be a companion for your smarthome like HomeAssistant, IOBroker, NodeRed and so on. Even if you don't have a Smarthome system, but would like to experiment with NodeRed or N8N, you are still welcome to join us. @@ -40,7 +41,9 @@ Join the thousands of satisfied awtrix users who have already chosen Awtrix 2 an - Onscreen menu where you can change your settings directly on the device - Pre-installed Apps like time, date, temperature, humidity and battery - Add customapps without recompiling straight from your Smarthome. -- Noitification support +- Notification support +- Animated icons +- Custom icons without recompiling - Easy to use icon system - Powerful MQTT commands - HTTP API diff --git a/docs/api.md b/docs/api.md index 24ef510..daefb3f 100644 --- a/docs/api.md +++ b/docs/api.md @@ -43,7 +43,7 @@ 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 what is sent. | 0 | All keys are optional, so you can send just the properties you want to use. @@ -222,7 +222,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": @@ -235,3 +235,11 @@ Here's an example JSON object to start a timer for 1 hour, 30 minutes, and 10 se } ``` +## Turn display on or off +| Topic | URL | Payload/Body | HTTP method | +| --- | --- | --- | --- | +| `[PREFIX]/onstate` | `http://[IP]/api/onstate` | `{"state":value}` | POST | + +Valid values are: +- `0` => off +- `1` => on diff --git a/docs/flasher.md b/docs/flasher.md index 0338bec..2e92874 100644 --- a/docs/flasher.md +++ b/docs/flasher.md @@ -2,6 +2,6 @@ # Online flasher Available in Google Chrome and Microsoft Edge browsers. -If you falsh your Ulanzi Clock the first time you need to check "erase". +If you flash your Ulanzi Clock the first time you need to check "erase". [filename](flasher/index.html ':include :type=iframe') diff --git a/docs/flasher/firmware/firmware.bin b/docs/flasher/firmware/firmware.bin index 7f6fe56..5d935fa 100644 Binary files a/docs/flasher/firmware/firmware.bin and b/docs/flasher/firmware/firmware.bin differ diff --git a/docs/flasher/firmware/manifest.json b/docs/flasher/firmware/manifest.json index 257a148..6f2cd1d 100644 --- a/docs/flasher/firmware/manifest.json +++ b/docs/flasher/firmware/manifest.json @@ -1,6 +1,6 @@ { "name": "AWTRIX Light", - "version": "0.47", + "version": "0.48", "home_assistant_domain": "AwtrixLight", "funding_url": "https://blueforcer.de", "new_install_prompt_erase": true, diff --git a/docs/flasher/index.html b/docs/flasher/index.html index d479fe2..99d5e41 100644 --- a/docs/flasher/index.html +++ b/docs/flasher/index.html @@ -75,7 +75,7 @@ } } - +
diff --git a/src/DisplayManager.cpp b/src/DisplayManager.cpp index 834f7ed..7178137 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; @@ -421,7 +423,7 @@ void DisplayManager_::generateNotification(const char *json) else { notify.barSize = 0; - } + } if (doc.containsKey("color")) { @@ -473,7 +475,7 @@ void DisplayManager_::generateNotification(const char *json) } else { - fs::File nullPointer; + fs::File nullPointer; notify.icon = nullPointer; } } @@ -802,10 +804,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); } @@ -944,6 +948,32 @@ String DisplayManager_::getAppsAsJson() return json; } + +void DisplayManager_::onStateParse(const char *json) +{ + DynamicJsonDocument doc(512); + DeserializationError error = deserializeJson(doc, json); + if (error) + return; + bool state = doc["state"].as(); + onState(state); +} + +void DisplayManager_::onState(bool state) +{ + if (state) + { + MATRIX_OFF = false; + setBrightness(lastBrightness); + } + else + { + MATRIX_OFF = true; + lastBrightness = BRIGHTNESS; + setBrightness(0); + } +} + void DisplayManager_::setIndicator1(bool state, uint16_t color) { ui->setIndicator1(state, color); @@ -953,3 +983,4 @@ void DisplayManager_::setIndicator2(bool state, uint16_t color) { ui->setIndicator2(state, color); } + diff --git a/src/DisplayManager.h b/src/DisplayManager.h index 44caeeb..811751f 100644 --- a/src/DisplayManager.h +++ b/src/DisplayManager.h @@ -66,8 +66,13 @@ public: void setAppTime(uint16_t duration); String getAppsAsJson(); String getStat(); + + void onState(bool state); + void onStateParse(const char *json); + void setIndicator1(bool state, uint16_t color); void setIndicator2(bool state, uint16_t color); + }; extern DisplayManager_ &DisplayManager; diff --git a/src/MQTTManager.cpp b/src/MQTTManager.cpp index 281dd17..78c7de7 100644 --- a/src/MQTTManager.cpp +++ b/src/MQTTManager.cpp @@ -10,7 +10,6 @@ #include "UpdateManager.h" WiFiClient espClient; -uint8_t lastBrightness; HADevice device; HAMqtt mqtt(espClient, device, 25); @@ -123,17 +122,7 @@ void onStateCommand(bool state, HALight *sender) { if (sender == Matrix) { - if (state) - { - MATRIX_OFF = false; - DisplayManager.setBrightness(lastBrightness); - } - else - { - MATRIX_OFF = true; - lastBrightness = BRIGHTNESS; - DisplayManager.setBrightness(0); - } + DisplayManager.onState(state); } else if (sender == Indikator1) { @@ -143,7 +132,6 @@ void onStateCommand(bool state, HALight *sender) { DisplayManager.setIndicator2(state, 0); } - sender->setState(state); } @@ -153,7 +141,6 @@ void onBrightnessCommand(uint8_t brightness, HALight *sender) if (AUTO_BRIGHTNESS) return; BRIGHTNESS = brightness; - lastBrightness = brightness; saveSettings(); DisplayManager.setBrightness(brightness); } @@ -232,7 +219,13 @@ void onMqttMessage(const char *topic, const uint8_t *payload, uint16_t length) delete[] payloadCopy; return; } - + if (strTopic.equals(MQTT_PREFIX + "/onstate")) + { + DisplayManager.onStateParse(payloadCopy); + Serial.println(payloadCopy); + delete[] payloadCopy; + return; + } else if (strTopic.startsWith(MQTT_PREFIX + "/custom")) { String topic_str = topic; @@ -263,7 +256,8 @@ void onMqttConnected() "/nextapp", "/doupdate", "/nextapp", - "/apps"}; + "/apps", + "/onstate"}; for (const char *topic : topics) { String fullTopic = prefix + topic; @@ -297,7 +291,6 @@ char batID[40]; void MQTTManager_::setup() { - if (HA_DISCOVERY) { Serial.println(F("Starting Homeassistant discorvery")); @@ -406,8 +399,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..fa72d37 100644 --- a/src/ServerManager.cpp +++ b/src/ServerManager.cpp @@ -102,6 +102,8 @@ void ServerManager_::setup() mws.addHandler("/api/doupdate", HTTP_POST, []() { if (UPDATE_AVAILABLE) UpdateManager.updateFirmware(); mws.webserver->send(200,"OK"); }); + mws.addHandler("/api/onstate", HTTP_POST, []() + { DisplayManager.onStateParse(mws.webserver->arg("plain").c_str()); mws.webserver->send(200,"OK"); }); Serial.println("Webserver loaded"); } mws.addHandler("/version", HTTP_GET, versionHandler); diff --git a/version b/version index 4f009b9..8ae5e61 100644 --- a/version +++ b/version @@ -1 +1 @@ -0.47 +0.48