diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index f2496e1..1b91ac9 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -88,6 +88,7 @@ module.exports = { 'use/sensors', 'use/actuators', 'use/boards', + 'use/displays', 'use/gateway' ] }, diff --git a/docs/use/boards.md b/docs/use/boards.md index 9b518bd..da56091 100644 --- a/docs/use/boards.md +++ b/docs/use/boards.md @@ -84,65 +84,3 @@ OpenMQTTGateway support a low power mode for ESP32, this mode can be set by MQTT The low power mode can be changed also with a push to button B when the board is processing (top button on M5stickC, M5stickC Plus and middle button of M5stack). If you are already in low power mode 1 or 2 with M5Stack you can wake up the board by pressing the red button. - -## SSD1306 Display boards ( Heltec SX127X 433Mhz boards and LILYGO® LoRa32 V2.1_1.6.1 433 Mhz ) - -Several options are available for the display of information on the SSD1306 Display. These options include display of the OMG logo and setup messages, redirecting of the log output to the display, and display of various module messages on the display. These options are exclusive to each other, and when a different option is enabled, the current option is disabled. - -### Setting the log output - -The display of serial log messages to the display can be enabled via compiler directive `-DLOG_TO_LCD=true` or via MQTT commands. - -For example if you want to set the serial log to LCD - -`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoSSD1306 -m '{"log-lcd":true}'` - -you can also revert it back to the serial monitor: - -`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoSSD1306 -m '{"log-lcd":false}'` - -The log level of the messages displayed is Errors and Warnings, and this can only be changed via the compiler directive `-DLOG_LEVEL_LCD=LOG_LEVEL_NOTICE`. - -### Displaying Module json messages ( default ) - -The display of messages from various modules is also supported. Currently supported modules include `ZgatewayRTL_433` and `ZsensorBME280`. - -This can be enabled with the compiler directive `-DJSON_TO_LCD=true`. - -You can also change it by MQTT. For example if you want to display module json messages: - -`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoSSD1306 -m '{"json-lcd":true}'` - -And to disable the display of module json messages: - -`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoSSD1306 -m '{"display-json":false}'` - -### Units for display, Metric or Imperial - -By default the display uses metric units, and this can be changed either by compiler directive or mqtt command. - -The compiler directive is `-DDISPLAY_METRIC=true` - -The mqtt command to change the units is: - -`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoSSD1306 -m '{"display-metric":false}'` - -Please note that it may take several seconds/display updates for the units to change. This is due to the queueing of messages for display. - -### Flip Display 180 degrees - -This allows you to rotate the display 180 degrees. Can be set at compile time or during use, defaults to true. - -The compiler directive is `-DDISPLAY_FLIP=false` - -The mqtt command to change display orientation is: - -`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoSSD1306 -m '{"display-flip":false}'` - -Please note that it may take several seconds/display updates for the display to change. This is due to the queueing of messages for display. - -### Display OpenMQTTGateway Logo when Idle - -When this option is enabled the OLED display will show the OpenMQTTGateway Logo when it is idle. Defaults to false - -The compiler directive is `-DDISPLAY_IDLE_LOGO=true` \ No newline at end of file diff --git a/docs/use/displays.md b/docs/use/displays.md new file mode 100644 index 0000000..c93d42a --- /dev/null +++ b/docs/use/displays.md @@ -0,0 +1,86 @@ +# Displays + +## SSD1306 Display (Heltec SX127X and LILYGO® LoRa32 boards) +Several options are available for the display of information on the SSD1306 display. Some options are exclusive to each other, and when a different option is enabled, the current option is disabled. + +The current SSD1306 display states are being published to the `SSD1306toMQTT` topic, e.g. + +`{"onstate":true,"brightness":50,"display-metric":true,"display-flip":true,"idlelogo":true,"log-lcd":false,"json-lcd":true}` + +### Display ON/OFF +To turn the SSD1306 display on or off. + +This can be enabled with the compiler directive `-DDISPLAY_STATE=true`. + +MQTT Display OFF command: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoSSD1306/config -m {"onstate":false}` + +MQTT Display ON command: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoSSD1306/config -m {"onstate":true}` + +### Brightness +The display brightness can be set between 0-100%. + +It is recommended to set a value lower than 100 to extend the life of the OLED display. The default setting is 50. + +This can be set with the compiler directive `-DDISPLAY_BRIGHTNESS=50`. + +or with the runtime command + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoSSD1306/config -m {"brightness":50}` + +### Metric or Imperial property units +To have applicable device properties displayed in Imperial units, e.g. °F for temperature. + +This can be set with the compiler directive `-DDISPLAY_METRIC=false`. + +or with the runtime command + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoSSD1306/config -m {"display-metric":false}` + +### Rotating the display by 180 degrees + +This can be set with the compiler directive `-DDISPLAY_FLIP=false`. + +or with the runtime command + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoSSD1306/config -m {"display-flip":false}` + +### Display idle Logo +To display the OpenMQTTGateway logo during device display idle time. This reduces the likelihood of burn-in. + +This can be set with the compiler directive `-DDISPLAY_IDLE_LOGO=true`. + +or at runtime with + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoSSD1306/config -m {"idlelogo":true}` + +### Setting the log output + +The display of serial log messages to the display can be enabled via compiler directive `-DLOG_TO_LCD=true` or via MQTT commands. + +For example if you want to set the serial log to LCD + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoSSD1306/config -m '{"log-lcd":true}'` + +you can also revert it back to the serial monitor: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoSSD1306/config -m '{"log-lcd":false}'` + +The log level of the messages displayed is Errors and Warnings, and this can only be changed via the compiler directive `-DLOG_LEVEL_LCD=LOG_LEVEL_NOTICE`. + +### Displaying Module json messages (default) + +The display of messages from various modules is also supported. Currently supported modules include `ZgatewayRTL_433`, `ZgatewayBT` and `ZsensorBME280`. + +This can be enabled with the compiler directive `-DJSON_TO_LCD=true`. + +You can also change it by MQTT. For example if you want to display module json messages: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoSSD1306/config -m '{"json-lcd":true}'` + +And to disable the display of module json messages: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoSSD1306/config -m '{"display-json":false}'` diff --git a/environments.ini b/environments.ini index 5652c69..297e296 100644 --- a/environments.ini +++ b/environments.ini @@ -772,6 +772,7 @@ build_flags = ; '-DJSON_TO_LCD=true' ; '-DLOG_LEVEL_LCD=LOG_LEVEL_NOTICE' ; '-DDISPLAY_IDLE_LOGO=false' +; '-DDISPLAY_BRIGHTNESS=100' ; '-DDISPLAY_METRIC=false' custom_description = For ESP32, Gateway using RTL_433_ESP and RadioLib custom_hardware = ESP32 LILYGO LoRa32 V2.1 diff --git a/main/ZdisplaySSD1306.ino b/main/ZdisplaySSD1306.ino index 3ca577d..eed36a0 100644 --- a/main/ZdisplaySSD1306.ino +++ b/main/ZdisplaySSD1306.ino @@ -45,6 +45,9 @@ boolean logToLCDDisplay = LOG_TO_LCD; boolean jsonDisplay = JSON_TO_LCD; boolean displayMetric = DISPLAY_METRIC; boolean displayFlip = DISPLAY_FLIP; +boolean displayState = DISPLAY_STATE; +boolean idlelogo = DISPLAY_IDLE_LOGO; +uint8_t displayBrightness = round(DISPLAY_BRIGHTNESS * 2.55); /* Toogle log display @@ -99,20 +102,17 @@ void loopSSD1306() { } free(message); nextDisplayPage = uptime() + DISPLAY_PAGE_INTERVAL; + logoDisplayed = false; } } /* Display logo if it has been more than DISPLAY_PAGE_INTERVAL */ -# if DISPLAY_IDLE_LOGO - if (uptime() > nextDisplayPage + 1 && !logoDisplayed) { - Oled.fillScreen(WHITE); - Oled.drawLogo(); + if (uptime() > nextDisplayPage + 1 && !logoDisplayed && idlelogo) { + Oled.fillScreen(BLACK); + Oled.drawLogo(rand() % 13 - 5, rand() % 32 - 13); logoDisplayed = true; - } else { - logoDisplayed = false; } -# endif } /* @@ -125,7 +125,21 @@ void MQTTtoSSD1306(char* topicOri, JsonObject& SSD1306data) { // json object dec if (cmpToMainTopic(topicOri, subjectMQTTtoSSD1306set)) { Log.trace(F("MQTTtoSSD1306 json set" CR)); // Log display set between SSD1306 lcd (true) and serial monitor (false) - if (SSD1306data.containsKey("log-lcd")) { + if (SSD1306data.containsKey("onstate")) { + if (displayState != SSD1306data["onstate"]) { + displayState = SSD1306data["onstate"]; + Oled.begin(); + } + displayState = SSD1306data["onstate"]; + Log.notice(F("Set display state: %T" CR), logToLCDDisplay); + success = true; + } else if (SSD1306data.containsKey("brightness")) { + displayBrightness = SSD1306data["brightness"]; + displayBrightness = round(displayBrightness * 2.55); + Oled.display->setBrightness(displayBrightness); + Log.notice(F("Set brightness: %d" CR), displayBrightness); + success = true; + } else if (SSD1306data.containsKey("log-lcd")) { logToLCDDisplay = SSD1306data["log-lcd"]; Log.notice(F("Set lcd log: %T" CR), logToLCDDisplay); logToLCD(logToLCDDisplay); @@ -145,6 +159,9 @@ void MQTTtoSSD1306(char* topicOri, JsonObject& SSD1306data) { // json object dec displayMetric = SSD1306data["display-metric"]; Log.notice(F("Set display-metric: %T" CR), displayMetric); success = true; + } else if (SSD1306data.containsKey("idlelogo")) { + idlelogo = SSD1306data["idlelogo"]; + success = true; } else if (SSD1306data.containsKey("display-flip")) { displayFlip = SSD1306data["display-flip"]; Log.notice(F("Set display-flip: %T" CR), displayFlip); @@ -156,9 +173,9 @@ void MQTTtoSSD1306(char* topicOri, JsonObject& SSD1306data) { // json object dec success = true; } if (success) { - pub(subjectSSD1306toMQTTset, SSD1306data); + stateSSD1306Display(); } else { - pub(subjectSSD1306toMQTTset, "{\"Status\": \"Error\"}"); // Fail feedback + pub(subjectSSD1306toMQTT, "{\"Status\": \"Error\"}"); // Fail feedback Log.error(F("[ SSD1306 ] MQTTtoSSD1306 Fail json" CR), SSD1306data); } } @@ -182,6 +199,9 @@ void ssd1306PubPrint(const char* topicori, JsonObject& data) { strlcpy(message->title, strtok(topic, "/"), OLED_TEXT_WIDTH); free(topic); + Oled.display->normalDisplay(); + // Oled.display->normalDisplay(); + switch (hash(message->title)) { case hash("SYStoMQTT"): { // {"uptime":456356,"version":"lilygo-rtl_433-test-A-v1.1.1-25-g574177d[lily-cloud]","freemem":125488,"mqttport":"1883","mqttsecure":false,"freestack":3752,"rssi":-36,"SSID":"The_Beach","BSSID":"64:A5:C3:69:C3:38","ip":"192.168.1.239","mac":"4C:75:25:A8:D5:D8","actRec":3,"mhz":433.92,"RTLRssiThresh":-98,"RTLRssi":-108,"RTLAVGRssi":-107,"RTLCnt":121707,"RTLOOKThresh":90,"modules":["LILYGO_OLED","CLOUD","rtl_433"]} @@ -486,18 +506,21 @@ void OledSerial::begin() { xSemaphoreGive(semaphoreOLEDOperation); display->init(); - if (displayFlip) { - display->flipScreenVertically(); + if (displayState) { + if (displayFlip) { + display->flipScreenVertically(); + } else { + display->resetOrientation(); + } + display->setFont(ArialMT_Plain_10); + display->setBrightness(displayBrightness); + drawLogo(0, 0); + display->invertDisplay(); + display->setLogBuffer(OLED_TEXT_ROWS, OLED_TEXT_BUFFER); + delay(1000); } else { - display->resetOrientation(); + display->displayOff(); } - display->setFont(ArialMT_Plain_10); - display->setColor(WHITE); - display->fillRect(0, 0, OLED_WIDTH, OLED_HEIGHT); - display->display(); - drawLogo(); - display->setLogBuffer(OLED_TEXT_ROWS, OLED_TEXT_BUFFER); - delay(1000); } /* @@ -543,6 +566,7 @@ size_t OledSerial::write(const uint8_t* buffer, size_t size) { if (xPortGetCoreID() == CONFIG_ARDUINO_RUNNING_CORE) { if (xSemaphoreTake(semaphoreOLEDOperation, pdMS_TO_TICKS(30000)) == pdTRUE) { nextDisplayPage = uptime() + DISPLAY_PAGE_INTERVAL; + display->normalDisplay(); display->clear(); display->setColor(WHITE); display->setFont(ArialMT_Plain_10); @@ -590,38 +614,50 @@ boolean OledSerial::displayPage(displayQueueMessage* message) { /* Primitives behind OpenMQTTGateway logo */ -void OledSerial::drawLogo() { +void OledSerial::drawLogo(int xshift, int yshift) { if (xSemaphoreTake(semaphoreOLEDOperation, pdMS_TO_TICKS(30000)) == pdTRUE) { - display->setColor(BLACK); - + display->setColor(WHITE); // line 1 - display->drawLine(15, 28, 20, 31); - display->drawLine(15, 29, 20, 32); + display->drawLine(15 + xshift, 28 + yshift, 20 + xshift, 31 + yshift); + display->drawLine(15 + xshift, 29 + yshift, 20 + xshift, 32 + yshift); // line 2 - display->drawLine(25, 29, 22, 21); - display->drawLine(26, 29, 23, 21); + display->drawLine(25 + xshift, 29 + yshift, 22 + xshift, 21 + yshift); + display->drawLine(26 + xshift, 29 + yshift, 23 + xshift, 21 + yshift); // circle 1 - display->fillCircle(25, 35, 7); - display->setColor(WHITE); - display->fillCircle(25, 35, 5); + display->fillCircle(25 + xshift, 35 + yshift, 7); + display->setColor(BLACK); + display->fillCircle(25 + xshift, 35 + yshift, 5); // circle 2 - display->setColor(BLACK); - display->fillCircle(23, 18, 4); display->setColor(WHITE); - display->fillCircle(23, 18, 2); + display->fillCircle(23 + xshift, 18 + yshift, 4); + display->setColor(BLACK); + display->fillCircle(23 + xshift, 18 + yshift, 2); // circle 3 - display->setColor(BLACK); - display->fillCircle(11, 25, 5); display->setColor(WHITE); - display->fillCircle(11, 25, 3); - // name + display->fillCircle(11 + xshift, 25 + yshift, 5); display->setColor(BLACK); - display->drawString(32, 32, "penMQTTGateway"); + display->fillCircle(11 + xshift, 25 + yshift, 3); + // name + display->setColor(WHITE); + display->drawString(32 + xshift, 32 + yshift, "penMQTTGateway"); display->display(); - delay(50); xSemaphoreGive(semaphoreOLEDOperation); } } +void stateSSD1306Display() { + //Publish display state + StaticJsonDocument jsonBuffer; + JsonObject DISPLAYdata = jsonBuffer.to(); + DISPLAYdata["onstate"] = (bool)displayState; + DISPLAYdata["brightness"] = (int)round(displayBrightness / 2.55); + DISPLAYdata["display-metric"] = (bool)displayMetric; + DISPLAYdata["display-flip"] = (bool)displayFlip; + DISPLAYdata["idlelogo"] = (bool)idlelogo; + DISPLAYdata["log-lcd"] = (bool)logToLCDDisplay; + DISPLAYdata["json-lcd"] = (bool)jsonDisplay; + pub(subjectSSD1306toMQTT, DISPLAYdata); +} + #endif diff --git a/main/config_SSD1306.h b/main/config_SSD1306.h index 053c4a0..ae8d13c 100644 --- a/main/config_SSD1306.h +++ b/main/config_SSD1306.h @@ -59,7 +59,7 @@ #endif #ifndef DISPLAY_IDLE_LOGO -# define DISPLAY_IDLE_LOGO false // Display the OMG logo when idle +# define DISPLAY_IDLE_LOGO true // Display the OMG logo when idle #endif #ifndef DISPLAY_METRIC @@ -70,6 +70,14 @@ # define DISPLAY_FLIP true // Flip display orientation #endif +#ifndef DISPLAY_STATE +# define DISPLAY_STATE true // set to false if you don't want to use the display +#endif + +#ifndef DISPLAY_BRIGHTNESS +# define DISPLAY_BRIGHTNESS 50 // 0-100; 50 % brightness as default +#endif + /*------------------- DEFAULT DISPLAY GEOMETRY ----------------------*/ #define OLED_TEXT_BUFFER 1000 @@ -91,8 +99,8 @@ /*-------------------DEFINE MQTT TOPIC FOR CONFIG----------------------*/ -#define subjectMQTTtoSSD1306set "/commands/MQTTtoSSD1306" -#define subjectSSD1306toMQTTset "/SSD1306toMQTT" +#define subjectMQTTtoSSD1306set "/commands/MQTTtoSSD1306/config" +#define subjectSSD1306toMQTT "/SSD1306toMQTT" /*-------------------EXTERNAL FUNCTIONS----------------------*/ @@ -138,7 +146,7 @@ class OledSerial : public Stream { public: OledSerial(int); void begin(); - void drawLogo(); + void drawLogo(int xshift, int yshift); boolean displayPage(displayQueueMessage*); SSD1306Wire* display; diff --git a/main/main.ino b/main/main.ino index e091175..7af024f 100644 --- a/main/main.ino +++ b/main/main.ino @@ -1517,6 +1517,9 @@ void loop() { # endif # ifdef ZactuatorONOFF stateONOFFMeasures(); +# endif +# ifdef ZdisplaySSD1306 + stateSSD1306Display(); # endif } #endif