mirror of https://github.com/lumapu/ahoy.git
				
				
			
				 9 changed files with 428 additions and 539 deletions
			
			
		@ -1,19 +1,45 @@ | 
				
			|||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			|||
#pragma once | 
				
			|||
//-----------------------------------------------------------------------------
 | 
				
			|||
// 2023 Ahoy, https://ahoydtu.de
 | 
				
			|||
// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
 | 
				
			|||
//-----------------------------------------------------------------------------
 | 
				
			|||
 | 
				
			|||
#pragma once | 
				
			|||
#include <U8g2lib.h> | 
				
			|||
#define DISP_DEFAULT_TIMEOUT 60  // in seconds
 | 
				
			|||
#define DISP_FMT_TEXT_LEN 32 | 
				
			|||
#define BOTTOM_MARGIN 5 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
#ifdef ESP8266 | 
				
			|||
#include <ESP8266WiFi.h> | 
				
			|||
#elif defined(ESP32) | 
				
			|||
#include <WiFi.h> | 
				
			|||
#endif | 
				
			|||
#include "../../utils/helper.h" | 
				
			|||
 | 
				
			|||
class DisplayMono { | 
				
			|||
   public: | 
				
			|||
    DisplayMono(){}; | 
				
			|||
      DisplayMono() {}; | 
				
			|||
 | 
				
			|||
      virtual void init(uint8_t type, uint8_t rot, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t* utcTs, const char* version) = 0; | 
				
			|||
      virtual void config(bool enPowerSafe, bool enScreenSaver, uint8_t lum) = 0; | 
				
			|||
      virtual void loop(void) = 0; | 
				
			|||
      virtual void disp(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod) = 0; | 
				
			|||
 | 
				
			|||
   protected: | 
				
			|||
      U8G2* mDisplay; | 
				
			|||
 | 
				
			|||
      uint8_t mType; | 
				
			|||
      bool mEnPowerSafe, mEnScreenSaver; | 
				
			|||
      uint8_t mLuminance; | 
				
			|||
 | 
				
			|||
      uint8_t mLoopCnt; | 
				
			|||
      uint32_t* mUtcTs; | 
				
			|||
      uint8_t mLineXOffsets[5]; | 
				
			|||
      uint8_t mLineYOffsets[5]; | 
				
			|||
 | 
				
			|||
    virtual void init(uint8_t type, uint8_t rot, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t* utcTs, const char* version) = 0; | 
				
			|||
    virtual void config(bool enPowerSafe, bool enScreenSaver, uint8_t lum) = 0; | 
				
			|||
    virtual void loop(void) = 0; | 
				
			|||
    virtual void disp(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod) = 0; | 
				
			|||
      uint16_t mDispY; | 
				
			|||
 | 
				
			|||
   private: | 
				
			|||
}; | 
				
			|||
      uint8_t mExtra; | 
				
			|||
      uint16_t mTimeout; | 
				
			|||
      char mFmtText[DISP_FMT_TEXT_LEN];}; | 
				
			|||
 | 
				
			|||
@ -1,169 +0,0 @@ | 
				
			|||
 | 
				
			|||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			|||
#include "Display_Mono_128X32.h" | 
				
			|||
 | 
				
			|||
#include "Display_Mono.h" | 
				
			|||
 | 
				
			|||
#ifdef ESP8266 | 
				
			|||
#include <ESP8266WiFi.h> | 
				
			|||
#elif defined(ESP32) | 
				
			|||
#include <WiFi.h> | 
				
			|||
#endif | 
				
			|||
#include "../../utils/helper.h" | 
				
			|||
 | 
				
			|||
// #ifdef U8X8_HAVE_HW_SPI
 | 
				
			|||
// #include <SPI.h>
 | 
				
			|||
// #endif
 | 
				
			|||
// #ifdef U8X8_HAVE_HW_I2C
 | 
				
			|||
// #include <Wire.h>
 | 
				
			|||
// #endif
 | 
				
			|||
 | 
				
			|||
DisplayMono128X32::DisplayMono128X32() : DisplayMono::DisplayMono() { | 
				
			|||
    mEnPowerSafe = true; | 
				
			|||
    mEnScreenSaver = true; | 
				
			|||
    mLuminance = 60; | 
				
			|||
    _dispY = 0; | 
				
			|||
    mTimeout = DISP_DEFAULT_TIMEOUT;  // interval at which to power save (milliseconds)
 | 
				
			|||
    mUtcTs = NULL; | 
				
			|||
    mType = 0; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono128X32::init(uint8_t type, uint8_t rotation, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t *utcTs, const char *version) { | 
				
			|||
    if ((0 < type) && (type < 5)) { | 
				
			|||
        u8g2_cb_t *rot = (u8g2_cb_t *)((rotation != 0x00) ? U8G2_R2 : U8G2_R0); | 
				
			|||
        mType = type; | 
				
			|||
        mDisplay = new U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C(rot, reset, clock, data); | 
				
			|||
 | 
				
			|||
        mUtcTs = utcTs; | 
				
			|||
 | 
				
			|||
        mDisplay->begin(); | 
				
			|||
 | 
				
			|||
        calcLinePositions(); | 
				
			|||
 | 
				
			|||
        mDisplay->clearBuffer(); | 
				
			|||
        mDisplay->setContrast(mLuminance); | 
				
			|||
        printText("AHOY!", 0); | 
				
			|||
        printText("ahoydtu.de", 2); | 
				
			|||
        printText(version, 3); | 
				
			|||
        mDisplay->sendBuffer(); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono128X32::config(bool enPowerSafe, bool enScreenSaver, uint8_t lum) { | 
				
			|||
    mEnPowerSafe = enPowerSafe; | 
				
			|||
    mEnScreenSaver = enScreenSaver; | 
				
			|||
    mLuminance = lum; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono128X32::loop(void) { | 
				
			|||
    if (mEnPowerSafe) | 
				
			|||
        if (mTimeout != 0) | 
				
			|||
            mTimeout--; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono128X32::disp(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod) { | 
				
			|||
    mDisplay->clearBuffer(); | 
				
			|||
 | 
				
			|||
    // set Contrast of the Display to raise the lifetime
 | 
				
			|||
    if (3 != mType) | 
				
			|||
        mDisplay->setContrast(mLuminance); | 
				
			|||
 | 
				
			|||
    if ((totalPower > 0) && (isprod > 0)) { | 
				
			|||
        mTimeout = DISP_DEFAULT_TIMEOUT; | 
				
			|||
        mDisplay->setPowerSave(false); | 
				
			|||
        if (totalPower > 999) { | 
				
			|||
            snprintf(_fmtText, DISP_FMT_TEXT_LEN, "%2.2f kW", (totalPower / 1000)); | 
				
			|||
        } else { | 
				
			|||
            snprintf(_fmtText, DISP_FMT_TEXT_LEN, "%3.0f W", totalPower); | 
				
			|||
        } | 
				
			|||
        printText(_fmtText, 0); | 
				
			|||
    } else { | 
				
			|||
        printText("offline", 0); | 
				
			|||
        // check if it's time to enter power saving mode
 | 
				
			|||
        if (mTimeout == 0) | 
				
			|||
            mDisplay->setPowerSave(mEnPowerSafe); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    snprintf(_fmtText, DISP_FMT_TEXT_LEN, "today: %4.0f Wh", totalYieldDay); | 
				
			|||
    printText(_fmtText, 1); | 
				
			|||
 | 
				
			|||
    snprintf(_fmtText, DISP_FMT_TEXT_LEN, "total: %.1f kWh", totalYieldTotal); | 
				
			|||
    printText(_fmtText, 2); | 
				
			|||
 | 
				
			|||
    IPAddress ip = WiFi.localIP(); | 
				
			|||
    if (!(_mExtra % 10) && (ip)) { | 
				
			|||
        printText(ip.toString().c_str(), 3); | 
				
			|||
    } else if (!(_mExtra % 5)) { | 
				
			|||
        snprintf(_fmtText, DISP_FMT_TEXT_LEN, "%d Inverter on", isprod); | 
				
			|||
        printText(_fmtText, 3); | 
				
			|||
    } else { | 
				
			|||
        if (NULL != mUtcTs) { | 
				
			|||
            printText(ah::getTimeStr(gTimezone.toLocal(*mUtcTs)).c_str(), 3); | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    mDisplay->sendBuffer(); | 
				
			|||
 | 
				
			|||
    _dispY = 0; | 
				
			|||
    _mExtra++; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono128X32::calcLinePositions() { | 
				
			|||
    uint8_t yOff[] = {0, 0}; | 
				
			|||
    for (uint8_t i = 0; i < 4; i++) { | 
				
			|||
        setFont(i); | 
				
			|||
        yOff[getColumn(i)] += (mDisplay->getMaxCharHeight()); | 
				
			|||
        mLineYOffsets[i] = yOff[getColumn(i)]; | 
				
			|||
        if (isTwoRowLine(i)) { | 
				
			|||
            yOff[getColumn(i)] += mDisplay->getMaxCharHeight(); | 
				
			|||
        } | 
				
			|||
        yOff[getColumn(i)] += BOTTOM_MARGIN; | 
				
			|||
        mLineXOffsets[i] = (getColumn(i) == 1 ? 80 : 0); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
inline void DisplayMono128X32::setFont(uint8_t line) { | 
				
			|||
    switch (line) { | 
				
			|||
        case 0: | 
				
			|||
 | 
				
			|||
            mDisplay->setFont(u8g2_font_9x15_tf); | 
				
			|||
            break; | 
				
			|||
        case 3: | 
				
			|||
            mDisplay->setFont(u8g2_font_tom_thumb_4x6_tf); | 
				
			|||
            break; | 
				
			|||
        default: | 
				
			|||
            mDisplay->setFont(u8g2_font_tom_thumb_4x6_tf); | 
				
			|||
            break; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
inline uint8_t DisplayMono128X32::getColumn(uint8_t line) { | 
				
			|||
    if (line >= 1 && line <= 2) { | 
				
			|||
        return 1; | 
				
			|||
    } else { | 
				
			|||
        return 0; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
inline bool DisplayMono128X32::isTwoRowLine(uint8_t line) { | 
				
			|||
    if (line >= 1 && line <= 2) { | 
				
			|||
        return true; | 
				
			|||
    } else { | 
				
			|||
        return false; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
void DisplayMono128X32::printText(const char *text, uint8_t line) { | 
				
			|||
    setFont(line); | 
				
			|||
 | 
				
			|||
    uint8_t dispX = mLineXOffsets[line] + ((mEnScreenSaver) ? (_mExtra % 7) : 0); | 
				
			|||
 | 
				
			|||
    if (isTwoRowLine(line)) { | 
				
			|||
        String stringText = String(text); | 
				
			|||
        int space = stringText.indexOf(" "); | 
				
			|||
        mDisplay->drawStr(dispX, mLineYOffsets[line], stringText.substring(0, space).c_str()); | 
				
			|||
        if (space > 0) | 
				
			|||
            mDisplay->drawStr(dispX, mLineYOffsets[line] + mDisplay->getMaxCharHeight(), stringText.substring(space + 1).c_str()); | 
				
			|||
    } else { | 
				
			|||
        mDisplay->drawStr(dispX, mLineYOffsets[line], text); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -1,37 +1,155 @@ | 
				
			|||
//-----------------------------------------------------------------------------
 | 
				
			|||
// 2023 Ahoy, https://ahoydtu.de
 | 
				
			|||
// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
 | 
				
			|||
//-----------------------------------------------------------------------------
 | 
				
			|||
 | 
				
			|||
#pragma once | 
				
			|||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			|||
#include "Display_Mono.h" | 
				
			|||
 | 
				
			|||
class DisplayMono128X32 : public DisplayMono { | 
				
			|||
   public: | 
				
			|||
    DisplayMono128X32(); | 
				
			|||
    public: | 
				
			|||
        DisplayMono128X32() : DisplayMono() { | 
				
			|||
            mEnPowerSafe = true; | 
				
			|||
            mEnScreenSaver = true; | 
				
			|||
            mLuminance = 60; | 
				
			|||
            mExtra = 0; | 
				
			|||
            mDispY = 0; | 
				
			|||
            mTimeout = DISP_DEFAULT_TIMEOUT;  // interval at which to power save (milliseconds)
 | 
				
			|||
            mUtcTs = NULL; | 
				
			|||
            mType = 0; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
        void init(uint8_t type, uint8_t rotation, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t *utcTs, const char *version) { | 
				
			|||
            if((0 == type) || (type > 4)) | 
				
			|||
                return; | 
				
			|||
 | 
				
			|||
            u8g2_cb_t *rot = (u8g2_cb_t *)((rotation != 0x00) ? U8G2_R2 : U8G2_R0); | 
				
			|||
            mType = type; | 
				
			|||
            mDisplay = new U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C(rot, reset, clock, data); | 
				
			|||
 | 
				
			|||
            mUtcTs = utcTs; | 
				
			|||
 | 
				
			|||
            mDisplay->begin(); | 
				
			|||
 | 
				
			|||
            calcLinePositions(); | 
				
			|||
 | 
				
			|||
            mDisplay->clearBuffer(); | 
				
			|||
            mDisplay->setContrast(mLuminance); | 
				
			|||
            printText("AHOY!", 0); | 
				
			|||
            printText("ahoydtu.de", 2); | 
				
			|||
            printText(version, 3); | 
				
			|||
            mDisplay->sendBuffer(); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        void config(bool enPowerSafe, bool enScreenSaver, uint8_t lum) { | 
				
			|||
            mEnPowerSafe = enPowerSafe; | 
				
			|||
            mEnScreenSaver = enScreenSaver; | 
				
			|||
            mLuminance = lum; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        void loop(void) { | 
				
			|||
            if (mEnPowerSafe) { | 
				
			|||
                if (mTimeout != 0) | 
				
			|||
                    mTimeout--; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        void disp(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod) { | 
				
			|||
            mDisplay->clearBuffer(); | 
				
			|||
 | 
				
			|||
            // set Contrast of the Display to raise the lifetime
 | 
				
			|||
            if (3 != mType) | 
				
			|||
                mDisplay->setContrast(mLuminance); | 
				
			|||
 | 
				
			|||
            if ((totalPower > 0) && (isprod > 0)) { | 
				
			|||
                mTimeout = DISP_DEFAULT_TIMEOUT; | 
				
			|||
                mDisplay->setPowerSave(false); | 
				
			|||
                if (totalPower > 999) | 
				
			|||
                    snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%2.2f kW", (totalPower / 1000)); | 
				
			|||
                else | 
				
			|||
                    snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%3.0f W", totalPower); | 
				
			|||
 | 
				
			|||
                printText(mFmtText, 0); | 
				
			|||
            } else { | 
				
			|||
                printText("offline", 0); | 
				
			|||
                // check if it's time to enter power saving mode
 | 
				
			|||
                if (mTimeout == 0) | 
				
			|||
                    mDisplay->setPowerSave(mEnPowerSafe); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            snprintf(mFmtText, DISP_FMT_TEXT_LEN, "today: %4.0f Wh", totalYieldDay); | 
				
			|||
            printText(mFmtText, 1); | 
				
			|||
 | 
				
			|||
            snprintf(mFmtText, DISP_FMT_TEXT_LEN, "total: %.1f kWh", totalYieldTotal); | 
				
			|||
            printText(mFmtText, 2); | 
				
			|||
 | 
				
			|||
            IPAddress ip = WiFi.localIP(); | 
				
			|||
            if (!(mExtra % 10) && (ip)) | 
				
			|||
                printText(ip.toString().c_str(), 3); | 
				
			|||
            else if (!(mExtra % 5)) { | 
				
			|||
                snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%d Inverter on", isprod); | 
				
			|||
                printText(mFmtText, 3); | 
				
			|||
            } else if (NULL != mUtcTs) | 
				
			|||
                printText(ah::getTimeStr(gTimezone.toLocal(*mUtcTs)).c_str(), 3); | 
				
			|||
 | 
				
			|||
            mDisplay->sendBuffer(); | 
				
			|||
 | 
				
			|||
            mDispY = 0; | 
				
			|||
            mExtra++; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
    void init(uint8_t type, uint8_t rot, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t* utcTs, const char* version); | 
				
			|||
    void config(bool enPowerSafe, bool enScreenSaver, uint8_t lum); | 
				
			|||
    void loop(void); | 
				
			|||
    void disp(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod); | 
				
			|||
    private: | 
				
			|||
        void calcLinePositions() { | 
				
			|||
            uint8_t yOff[] = {0, 0}; | 
				
			|||
            for (uint8_t i = 0; i < 4; i++) { | 
				
			|||
                setFont(i); | 
				
			|||
                yOff[getColumn(i)] += (mDisplay->getMaxCharHeight()); | 
				
			|||
                mLineYOffsets[i] = yOff[getColumn(i)]; | 
				
			|||
                if (isTwoRowLine(i)) | 
				
			|||
                    yOff[getColumn(i)] += mDisplay->getMaxCharHeight(); | 
				
			|||
                yOff[getColumn(i)] += BOTTOM_MARGIN; | 
				
			|||
                mLineXOffsets[i] = (getColumn(i) == 1 ? 80 : 0); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
   private: | 
				
			|||
    void calcLinePositions(); | 
				
			|||
    void setFont(uint8_t line); | 
				
			|||
    uint8_t getColumn(uint8_t line); | 
				
			|||
    bool isTwoRowLine(uint8_t line); | 
				
			|||
    void printText(const char* text, uint8_t line); | 
				
			|||
        inline void setFont(uint8_t line) { | 
				
			|||
            switch (line) { | 
				
			|||
                case 0: | 
				
			|||
                    mDisplay->setFont(u8g2_font_9x15_tf); | 
				
			|||
                    break; | 
				
			|||
                case 3: | 
				
			|||
                    mDisplay->setFont(u8g2_font_tom_thumb_4x6_tf); | 
				
			|||
                    break; | 
				
			|||
                default: | 
				
			|||
                    mDisplay->setFont(u8g2_font_tom_thumb_4x6_tf); | 
				
			|||
                    break; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
    U8G2* mDisplay; | 
				
			|||
        inline uint8_t getColumn(uint8_t line) { | 
				
			|||
            if (line >= 1 && line <= 2) | 
				
			|||
                return 1; | 
				
			|||
            else | 
				
			|||
                return 0; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
    uint8_t mType; | 
				
			|||
    bool mEnPowerSafe, mEnScreenSaver; | 
				
			|||
    uint8_t mLuminance; | 
				
			|||
        inline bool isTwoRowLine(uint8_t line) { | 
				
			|||
            return ((line >= 1) && (line <= 2)); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
    uint8_t mLoopCnt; | 
				
			|||
    uint32_t* mUtcTs; | 
				
			|||
    uint8_t mLineXOffsets[5]; | 
				
			|||
    uint8_t mLineYOffsets[5]; | 
				
			|||
        void printText(const char *text, uint8_t line) { | 
				
			|||
            setFont(line); | 
				
			|||
 | 
				
			|||
    uint16_t _dispY; | 
				
			|||
            uint8_t dispX = mLineXOffsets[line] + ((mEnScreenSaver) ? (mExtra % 7) : 0); | 
				
			|||
 | 
				
			|||
    uint8_t _mExtra; | 
				
			|||
    uint16_t mTimeout; | 
				
			|||
    char _fmtText[DISP_FMT_TEXT_LEN]; | 
				
			|||
            if (isTwoRowLine(line)) { | 
				
			|||
                String stringText = String(text); | 
				
			|||
                int space = stringText.indexOf(" "); | 
				
			|||
                mDisplay->drawStr(dispX, mLineYOffsets[line], stringText.substring(0, space).c_str()); | 
				
			|||
                if (space > 0) | 
				
			|||
                    mDisplay->drawStr(dispX, mLineYOffsets[line] + mDisplay->getMaxCharHeight(), stringText.substring(space + 1).c_str()); | 
				
			|||
            } else | 
				
			|||
                mDisplay->drawStr(dispX, mLineYOffsets[line], text); | 
				
			|||
        } | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
@ -1,146 +0,0 @@ | 
				
			|||
 | 
				
			|||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			|||
#include "Display_Mono_128X64.h" | 
				
			|||
 | 
				
			|||
#include "Display_Mono.h" | 
				
			|||
 | 
				
			|||
#ifdef ESP8266 | 
				
			|||
#include <ESP8266WiFi.h> | 
				
			|||
#elif defined(ESP32) | 
				
			|||
#include <WiFi.h> | 
				
			|||
#endif | 
				
			|||
#include "../../utils/helper.h" | 
				
			|||
 | 
				
			|||
// #ifdef U8X8_HAVE_HW_SPI
 | 
				
			|||
// #include <SPI.h>
 | 
				
			|||
// #endif
 | 
				
			|||
// #ifdef U8X8_HAVE_HW_I2C
 | 
				
			|||
// #include <Wire.h>
 | 
				
			|||
// #endif
 | 
				
			|||
 | 
				
			|||
DisplayMono128X64::DisplayMono128X64() : DisplayMono::DisplayMono() { | 
				
			|||
    mEnPowerSafe = true; | 
				
			|||
    mEnScreenSaver = true; | 
				
			|||
    mLuminance = 60; | 
				
			|||
    _dispY = 0; | 
				
			|||
    mTimeout = DISP_DEFAULT_TIMEOUT;  // interval at which to power save (milliseconds)
 | 
				
			|||
    mUtcTs = NULL; | 
				
			|||
    mType = 0; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono128X64::init(uint8_t type, uint8_t rotation, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t *utcTs, const char *version) { | 
				
			|||
    if ((0 < type) && (type < 5)) { | 
				
			|||
        u8g2_cb_t *rot = (u8g2_cb_t *)((rotation != 0x00) ? U8G2_R2 : U8G2_R0); | 
				
			|||
        mType = type; | 
				
			|||
        switch (type) { | 
				
			|||
            case 1: | 
				
			|||
                mDisplay = new U8G2_SSD1306_128X64_NONAME_F_HW_I2C(rot, reset, clock, data); | 
				
			|||
                break; | 
				
			|||
            default: | 
				
			|||
            case 2: | 
				
			|||
                mDisplay = new U8G2_SH1106_128X64_NONAME_F_HW_I2C(rot, reset, clock, data); | 
				
			|||
                break; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        mUtcTs = utcTs; | 
				
			|||
 | 
				
			|||
        mDisplay->begin(); | 
				
			|||
 | 
				
			|||
        calcLineHeights(); | 
				
			|||
 | 
				
			|||
        mDisplay->clearBuffer(); | 
				
			|||
        mDisplay->setContrast(mLuminance); | 
				
			|||
        printText("AHOY!", 0, 35); | 
				
			|||
        printText("ahoydtu.de", 2, 20); | 
				
			|||
        printText(version, 3, 46); | 
				
			|||
        mDisplay->sendBuffer(); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono128X64::config(bool enPowerSafe, bool enScreenSaver, uint8_t lum) { | 
				
			|||
    mEnPowerSafe = enPowerSafe; | 
				
			|||
    mEnScreenSaver = enScreenSaver; | 
				
			|||
    mLuminance = lum; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono128X64::loop(void) { | 
				
			|||
    if (mEnPowerSafe) | 
				
			|||
        if (mTimeout != 0) | 
				
			|||
            mTimeout--; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono128X64::disp(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod) { | 
				
			|||
    mDisplay->clearBuffer(); | 
				
			|||
 | 
				
			|||
    // set Contrast of the Display to raise the lifetime
 | 
				
			|||
    if (3 != mType) | 
				
			|||
        mDisplay->setContrast(mLuminance); | 
				
			|||
 | 
				
			|||
    if ((totalPower > 0) && (isprod > 0)) { | 
				
			|||
        mTimeout = DISP_DEFAULT_TIMEOUT; | 
				
			|||
        mDisplay->setPowerSave(false); | 
				
			|||
        if (totalPower > 999) { | 
				
			|||
            snprintf(_fmtText, DISP_FMT_TEXT_LEN, "%2.2f kW", (totalPower / 1000)); | 
				
			|||
        } else { | 
				
			|||
            snprintf(_fmtText, DISP_FMT_TEXT_LEN, "%3.0f W", totalPower); | 
				
			|||
        } | 
				
			|||
        printText(_fmtText, 0); | 
				
			|||
    } else { | 
				
			|||
        printText("offline", 0, 25); | 
				
			|||
        // check if it's time to enter power saving mode
 | 
				
			|||
        if (mTimeout == 0) | 
				
			|||
            mDisplay->setPowerSave(mEnPowerSafe); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    snprintf(_fmtText, DISP_FMT_TEXT_LEN, "today: %4.0f Wh", totalYieldDay); | 
				
			|||
    printText(_fmtText, 1); | 
				
			|||
 | 
				
			|||
    snprintf(_fmtText, DISP_FMT_TEXT_LEN, "total: %.1f kWh", totalYieldTotal); | 
				
			|||
    printText(_fmtText, 2); | 
				
			|||
 | 
				
			|||
    IPAddress ip = WiFi.localIP(); | 
				
			|||
    if (!(_mExtra % 10) && (ip)) { | 
				
			|||
        printText(ip.toString().c_str(), 3); | 
				
			|||
    } else if (!(_mExtra % 5)) { | 
				
			|||
        snprintf(_fmtText, DISP_FMT_TEXT_LEN, "%d Inverter on", isprod); | 
				
			|||
        printText(_fmtText, 3); | 
				
			|||
    } else { | 
				
			|||
        if (NULL != mUtcTs) { | 
				
			|||
            printText(ah::getDateTimeStr(gTimezone.toLocal(*mUtcTs)).c_str(), 3); | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    mDisplay->sendBuffer(); | 
				
			|||
 | 
				
			|||
    _dispY = 0; | 
				
			|||
    _mExtra++; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono128X64::calcLineHeights() { | 
				
			|||
    uint8_t yOff = 0; | 
				
			|||
    for (uint8_t i = 0; i < 4; i++) { | 
				
			|||
        setFont(i); | 
				
			|||
        yOff += (mDisplay->getMaxCharHeight()); | 
				
			|||
        mLineOffsets[i] = yOff; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
inline void DisplayMono128X64::setFont(uint8_t line) { | 
				
			|||
    switch (line) { | 
				
			|||
        case 0: | 
				
			|||
            mDisplay->setFont(u8g2_font_ncenB14_tr); | 
				
			|||
            break; | 
				
			|||
        case 3: | 
				
			|||
            mDisplay->setFont(u8g2_font_5x8_tr); | 
				
			|||
            break; | 
				
			|||
        default: | 
				
			|||
            mDisplay->setFont(u8g2_font_ncenB10_tr); | 
				
			|||
            break; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
void DisplayMono128X64::printText(const char *text, uint8_t line, uint8_t dispX) { | 
				
			|||
    setFont(line); | 
				
			|||
 | 
				
			|||
    dispX += (mEnScreenSaver) ? (_mExtra % 7) : 0; | 
				
			|||
    mDisplay->drawStr(dispX, mLineOffsets[line], text); | 
				
			|||
} | 
				
			|||
@ -1,36 +1,138 @@ | 
				
			|||
//-----------------------------------------------------------------------------
 | 
				
			|||
// 2023 Ahoy, https://ahoydtu.de
 | 
				
			|||
// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
 | 
				
			|||
//-----------------------------------------------------------------------------
 | 
				
			|||
 | 
				
			|||
#pragma once | 
				
			|||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			|||
#include "Display_Mono.h" | 
				
			|||
 | 
				
			|||
class DisplayMono128X64 : public DisplayMono { | 
				
			|||
   public: | 
				
			|||
    DisplayMono128X64(); | 
				
			|||
    public: | 
				
			|||
        DisplayMono128X64() : DisplayMono() { | 
				
			|||
            mEnPowerSafe = true; | 
				
			|||
            mEnScreenSaver = true; | 
				
			|||
            mLuminance = 60; | 
				
			|||
            mDispY = 0; | 
				
			|||
            mTimeout = DISP_DEFAULT_TIMEOUT;  // interval at which to power save (milliseconds)
 | 
				
			|||
            mUtcTs = NULL; | 
				
			|||
            mType = 0; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        void init(uint8_t type, uint8_t rotation, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t *utcTs, const char *version) { | 
				
			|||
            if((0 == type) || (type > 4)) | 
				
			|||
                return; | 
				
			|||
 | 
				
			|||
            u8g2_cb_t *rot = (u8g2_cb_t *)((rotation != 0x00) ? U8G2_R2 : U8G2_R0); | 
				
			|||
            mType = type; | 
				
			|||
 | 
				
			|||
            switch (type) { | 
				
			|||
                case 1: | 
				
			|||
                    mDisplay = new U8G2_SSD1306_128X64_NONAME_F_HW_I2C(rot, reset, clock, data); | 
				
			|||
                    break; | 
				
			|||
                default: | 
				
			|||
                case 2: | 
				
			|||
                    mDisplay = new U8G2_SH1106_128X64_NONAME_F_HW_I2C(rot, reset, clock, data); | 
				
			|||
                    break; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            mUtcTs = utcTs; | 
				
			|||
 | 
				
			|||
            mDisplay->begin(); | 
				
			|||
            calcLinePositions(); | 
				
			|||
 | 
				
			|||
            mDisplay->clearBuffer(); | 
				
			|||
            mDisplay->setContrast(mLuminance); | 
				
			|||
            printText("AHOY!", 0, 35); | 
				
			|||
            printText("ahoydtu.de", 2, 20); | 
				
			|||
            printText(version, 3, 46); | 
				
			|||
            mDisplay->sendBuffer(); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        void config(bool enPowerSafe, bool enScreenSaver, uint8_t lum) { | 
				
			|||
            mEnPowerSafe = enPowerSafe; | 
				
			|||
            mEnScreenSaver = enScreenSaver; | 
				
			|||
            mLuminance = lum; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        void loop(void) { | 
				
			|||
            if (mEnPowerSafe) { | 
				
			|||
                if (mTimeout != 0) | 
				
			|||
                    mTimeout--; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        void disp(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod) { | 
				
			|||
            mDisplay->clearBuffer(); | 
				
			|||
 | 
				
			|||
            // set Contrast of the Display to raise the lifetime
 | 
				
			|||
            if (3 != mType) | 
				
			|||
                mDisplay->setContrast(mLuminance); | 
				
			|||
 | 
				
			|||
            if ((totalPower > 0) && (isprod > 0)) { | 
				
			|||
                mTimeout = DISP_DEFAULT_TIMEOUT; | 
				
			|||
                mDisplay->setPowerSave(false); | 
				
			|||
 | 
				
			|||
                if (totalPower > 999) | 
				
			|||
                    snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%2.2f kW", (totalPower / 1000)); | 
				
			|||
                else | 
				
			|||
                    snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%3.0f W", totalPower); | 
				
			|||
 | 
				
			|||
                printText(mFmtText, 0); | 
				
			|||
            } else { | 
				
			|||
                printText("offline", 0, 25); | 
				
			|||
                // check if it's time to enter power saving mode
 | 
				
			|||
                if (mTimeout == 0) | 
				
			|||
                mDisplay->setPowerSave(mEnPowerSafe); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            snprintf(mFmtText, DISP_FMT_TEXT_LEN, "today: %4.0f Wh", totalYieldDay); | 
				
			|||
            printText(mFmtText, 1); | 
				
			|||
 | 
				
			|||
    void init(uint8_t type, uint8_t rot, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t* utcTs, const char* version); | 
				
			|||
    void config(bool enPowerSafe, bool enScreenSaver, uint8_t lum); | 
				
			|||
    void loop(void); | 
				
			|||
    void disp(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod); | 
				
			|||
            snprintf(mFmtText, DISP_FMT_TEXT_LEN, "total: %.1f kWh", totalYieldTotal); | 
				
			|||
            printText(mFmtText, 2); | 
				
			|||
 | 
				
			|||
   private: | 
				
			|||
    void calcLineHeights(); | 
				
			|||
    void setFont(uint8_t line); | 
				
			|||
    uint8_t getColumn(uint8_t line); | 
				
			|||
    bool isTwoRowLine(uint8_t line); | 
				
			|||
    void printText(const char* text, uint8_t line, uint8_t dispX = 5); | 
				
			|||
            IPAddress ip = WiFi.localIP(); | 
				
			|||
            if (!(mExtra % 10) && (ip)) | 
				
			|||
                printText(ip.toString().c_str(), 3); | 
				
			|||
            else if (!(mExtra % 5)) { | 
				
			|||
                snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%d Inverter on", isprod); | 
				
			|||
                printText(mFmtText, 3); | 
				
			|||
            } else  if (NULL != mUtcTs) | 
				
			|||
                printText(ah::getDateTimeStr(gTimezone.toLocal(*mUtcTs)).c_str(), 3); | 
				
			|||
 | 
				
			|||
    U8G2* mDisplay; | 
				
			|||
            mDisplay->sendBuffer(); | 
				
			|||
 | 
				
			|||
    uint8_t mType; | 
				
			|||
    bool mEnPowerSafe, mEnScreenSaver; | 
				
			|||
    uint8_t mLuminance; | 
				
			|||
            mDispY = 0; | 
				
			|||
            mExtra++; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
    uint8_t mLoopCnt; | 
				
			|||
    uint32_t* mUtcTs; | 
				
			|||
    uint8_t mLineOffsets[5]; | 
				
			|||
    private: | 
				
			|||
        void calcLinePositions() { | 
				
			|||
            uint8_t yOff = 0; | 
				
			|||
            for (uint8_t i = 0; i < 4; i++) { | 
				
			|||
                setFont(i); | 
				
			|||
                yOff += (mDisplay->getMaxCharHeight()); | 
				
			|||
                mLineYOffsets[i] = yOff; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
    uint16_t _dispY; | 
				
			|||
        inline void setFont(uint8_t line) { | 
				
			|||
            switch (line) { | 
				
			|||
                case 0: | 
				
			|||
                    mDisplay->setFont(u8g2_font_ncenB14_tr); | 
				
			|||
                    break; | 
				
			|||
                case 3: | 
				
			|||
                    mDisplay->setFont(u8g2_font_5x8_tr); | 
				
			|||
                    break; | 
				
			|||
                default: | 
				
			|||
                    mDisplay->setFont(u8g2_font_ncenB10_tr); | 
				
			|||
                    break; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
        void printText(const char *text, uint8_t line, uint8_t dispX = 5) { | 
				
			|||
            setFont(line); | 
				
			|||
 | 
				
			|||
    uint8_t _mExtra; | 
				
			|||
    uint16_t mTimeout; | 
				
			|||
    char _fmtText[DISP_FMT_TEXT_LEN]; | 
				
			|||
            dispX += (mEnScreenSaver) ? (mExtra % 7) : 0; | 
				
			|||
            mDisplay->drawStr(dispX, mLineYOffsets[line], text); | 
				
			|||
        } | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
@ -1,140 +0,0 @@ | 
				
			|||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			|||
#include "Display_Mono_84X48.h" | 
				
			|||
 | 
				
			|||
#include "Display_Mono.h" | 
				
			|||
 | 
				
			|||
#ifdef ESP8266 | 
				
			|||
#include <ESP8266WiFi.h> | 
				
			|||
#elif defined(ESP32) | 
				
			|||
#include <WiFi.h> | 
				
			|||
#endif | 
				
			|||
#include "../../utils/helper.h" | 
				
			|||
 | 
				
			|||
// #ifdef U8X8_HAVE_HW_SPI
 | 
				
			|||
// #include <SPI.h>
 | 
				
			|||
// #endif
 | 
				
			|||
// #ifdef U8X8_HAVE_HW_I2C
 | 
				
			|||
// #include <Wire.h>
 | 
				
			|||
// #endif
 | 
				
			|||
 | 
				
			|||
DisplayMono84X48::DisplayMono84X48() : DisplayMono::DisplayMono() { | 
				
			|||
    mEnPowerSafe = true; | 
				
			|||
    mEnScreenSaver = true; | 
				
			|||
    mLuminance = 60; | 
				
			|||
    _dispY = 0; | 
				
			|||
    mTimeout = DISP_DEFAULT_TIMEOUT;  // interval at which to power save (milliseconds)
 | 
				
			|||
    mUtcTs = NULL; | 
				
			|||
    mType = 0; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono84X48::init(uint8_t type, uint8_t rotation, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t *utcTs, const char *version) { | 
				
			|||
    if ((0 < type) && (type < 5)) { | 
				
			|||
        u8g2_cb_t *rot = (u8g2_cb_t *)((rotation != 0x00) ? U8G2_R2 : U8G2_R0); | 
				
			|||
        mType = type; | 
				
			|||
        mDisplay = new U8G2_PCD8544_84X48_F_4W_SW_SPI(rot, clock, data, cs, dc, reset); | 
				
			|||
 | 
				
			|||
        mUtcTs = utcTs; | 
				
			|||
 | 
				
			|||
        mDisplay->begin(); | 
				
			|||
 | 
				
			|||
        calcLineHeights(); | 
				
			|||
 | 
				
			|||
        mDisplay->clearBuffer(); | 
				
			|||
        if (3 != mType) | 
				
			|||
            mDisplay->setContrast(mLuminance); | 
				
			|||
        printText("AHOY!", 0); | 
				
			|||
        printText("ahoydtu.de", 2); | 
				
			|||
        printText(version, 3); | 
				
			|||
        mDisplay->sendBuffer(); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono84X48::config(bool enPowerSafe, bool enScreenSaver, uint8_t lum) { | 
				
			|||
    mEnPowerSafe = enPowerSafe; | 
				
			|||
    mEnScreenSaver = enScreenSaver; | 
				
			|||
    mLuminance = lum; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono84X48::loop(void) { | 
				
			|||
    if (mEnPowerSafe) | 
				
			|||
        if (mTimeout != 0) | 
				
			|||
            mTimeout--; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono84X48::disp(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod) { | 
				
			|||
    mDisplay->clearBuffer(); | 
				
			|||
 | 
				
			|||
    // set Contrast of the Display to raise the lifetime
 | 
				
			|||
    if (3 != mType) | 
				
			|||
        mDisplay->setContrast(mLuminance); | 
				
			|||
 | 
				
			|||
    if ((totalPower > 0) && (isprod > 0)) { | 
				
			|||
        mTimeout = DISP_DEFAULT_TIMEOUT; | 
				
			|||
        mDisplay->setPowerSave(false); | 
				
			|||
        if (totalPower > 999) { | 
				
			|||
            snprintf(_fmtText, DISP_FMT_TEXT_LEN, "%2.2f kW", (totalPower / 1000)); | 
				
			|||
        } else { | 
				
			|||
            snprintf(_fmtText, DISP_FMT_TEXT_LEN, "%3.0f W", totalPower); | 
				
			|||
        } | 
				
			|||
        printText(_fmtText, 0); | 
				
			|||
    } else { | 
				
			|||
        printText("offline", 0); | 
				
			|||
        // check if it's time to enter power saving mode
 | 
				
			|||
        if (mTimeout == 0) | 
				
			|||
            mDisplay->setPowerSave(mEnPowerSafe); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    snprintf(_fmtText, DISP_FMT_TEXT_LEN, "today: %4.0f Wh", totalYieldDay); | 
				
			|||
    printText(_fmtText, 1); | 
				
			|||
 | 
				
			|||
    snprintf(_fmtText, DISP_FMT_TEXT_LEN, "total: %.1f kWh", totalYieldTotal); | 
				
			|||
    printText(_fmtText, 2); | 
				
			|||
 | 
				
			|||
    IPAddress ip = WiFi.localIP(); | 
				
			|||
    if (!(_mExtra % 10) && (ip)) { | 
				
			|||
        printText(ip.toString().c_str(), 3); | 
				
			|||
    } else if (!(_mExtra % 5)) { | 
				
			|||
        snprintf(_fmtText, DISP_FMT_TEXT_LEN, "%d Inverter on", isprod); | 
				
			|||
        printText(_fmtText, 3); | 
				
			|||
    } else { | 
				
			|||
        if (NULL != mUtcTs) { | 
				
			|||
            printText(ah::getTimeStr(gTimezone.toLocal(*mUtcTs)).c_str(), 3); | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    mDisplay->sendBuffer(); | 
				
			|||
 | 
				
			|||
    _dispY = 0; | 
				
			|||
    _mExtra++; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono84X48::calcLineHeights() { | 
				
			|||
    uint8_t yOff = 0; | 
				
			|||
    for (uint8_t i = 0; i < 4; i++) { | 
				
			|||
        setFont(i); | 
				
			|||
        yOff += (mDisplay->getMaxCharHeight()); | 
				
			|||
        mLineOffsets[i] = yOff; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
inline void DisplayMono84X48::setFont(uint8_t line) { | 
				
			|||
    switch (line) { | 
				
			|||
        case 0: | 
				
			|||
            mDisplay->setFont(u8g2_font_logisoso16_tr); | 
				
			|||
            break; | 
				
			|||
        case 3: | 
				
			|||
            mDisplay->setFont(u8g2_font_5x8_tr); | 
				
			|||
            break; | 
				
			|||
        default: | 
				
			|||
            mDisplay->setFont(u8g2_font_5x8_tr); | 
				
			|||
            break; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono84X48::printText(const char *text, uint8_t line) { | 
				
			|||
    uint8_t dispX = (line == 0) ? 10 : 5; | 
				
			|||
    setFont(line); | 
				
			|||
 | 
				
			|||
    dispX += (mEnScreenSaver) ? (_mExtra % 7) : 0; | 
				
			|||
    mDisplay->drawStr(dispX, mLineOffsets[line], text); | 
				
			|||
} | 
				
			|||
@ -1,34 +1,132 @@ | 
				
			|||
//-----------------------------------------------------------------------------
 | 
				
			|||
// 2023 Ahoy, https://ahoydtu.de
 | 
				
			|||
// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
 | 
				
			|||
//-----------------------------------------------------------------------------
 | 
				
			|||
 | 
				
			|||
#pragma once | 
				
			|||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			|||
#include "Display_Mono.h" | 
				
			|||
 | 
				
			|||
class DisplayMono84X48 : public DisplayMono { | 
				
			|||
   public: | 
				
			|||
    DisplayMono84X48(); | 
				
			|||
    public: | 
				
			|||
        DisplayMono84X48() : DisplayMono() { | 
				
			|||
            mEnPowerSafe = true; | 
				
			|||
            mEnScreenSaver = true; | 
				
			|||
            mLuminance = 60; | 
				
			|||
            mExtra = 0; | 
				
			|||
            mDispY = 0; | 
				
			|||
            mTimeout = DISP_DEFAULT_TIMEOUT;  // interval at which to power save (milliseconds)
 | 
				
			|||
            mUtcTs = NULL; | 
				
			|||
            mType = 0; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        void init(uint8_t type, uint8_t rotation, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t *utcTs, const char *version) { | 
				
			|||
            if((0 == type) || (type > 4)) | 
				
			|||
                return; | 
				
			|||
 | 
				
			|||
            u8g2_cb_t *rot = (u8g2_cb_t *)((rotation != 0x00) ? U8G2_R2 : U8G2_R0); | 
				
			|||
            mType = type; | 
				
			|||
            mDisplay = new U8G2_PCD8544_84X48_F_4W_SW_SPI(rot, clock, data, cs, dc, reset); | 
				
			|||
 | 
				
			|||
            mUtcTs = utcTs; | 
				
			|||
 | 
				
			|||
            mDisplay->begin(); | 
				
			|||
            calcLinePositions(); | 
				
			|||
 | 
				
			|||
            mDisplay->clearBuffer(); | 
				
			|||
            if (3 != mType) | 
				
			|||
                mDisplay->setContrast(mLuminance); | 
				
			|||
            printText("AHOY!", 0); | 
				
			|||
            printText("ahoydtu.de", 2); | 
				
			|||
            printText(version, 3); | 
				
			|||
            mDisplay->sendBuffer(); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        void config(bool enPowerSafe, bool enScreenSaver, uint8_t lum) { | 
				
			|||
            mEnPowerSafe = enPowerSafe; | 
				
			|||
            mEnScreenSaver = enScreenSaver; | 
				
			|||
            mLuminance = lum; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        void loop(void) { | 
				
			|||
            if (mEnPowerSafe) { | 
				
			|||
                if (mTimeout != 0) | 
				
			|||
                        mTimeout--; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        void disp(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod) { | 
				
			|||
            mDisplay->clearBuffer(); | 
				
			|||
 | 
				
			|||
            // set Contrast of the Display to raise the lifetime
 | 
				
			|||
            if (3 != mType) | 
				
			|||
                mDisplay->setContrast(mLuminance); | 
				
			|||
 | 
				
			|||
            if ((totalPower > 0) && (isprod > 0)) { | 
				
			|||
                mTimeout = DISP_DEFAULT_TIMEOUT; | 
				
			|||
                mDisplay->setPowerSave(false); | 
				
			|||
 | 
				
			|||
                if (totalPower > 999) | 
				
			|||
                    snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%2.2f kW", (totalPower / 1000)); | 
				
			|||
                else | 
				
			|||
                    snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%3.0f W", totalPower); | 
				
			|||
 | 
				
			|||
                printText(mFmtText, 0); | 
				
			|||
            } else { | 
				
			|||
                printText("offline", 0); | 
				
			|||
                // check if it's time to enter power saving mode
 | 
				
			|||
                if (mTimeout == 0) | 
				
			|||
                    mDisplay->setPowerSave(mEnPowerSafe); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            snprintf(mFmtText, DISP_FMT_TEXT_LEN, "today: %4.0f Wh", totalYieldDay); | 
				
			|||
            printText(mFmtText, 1); | 
				
			|||
 | 
				
			|||
            snprintf(mFmtText, DISP_FMT_TEXT_LEN, "total: %.1f kWh", totalYieldTotal); | 
				
			|||
            printText(mFmtText, 2); | 
				
			|||
 | 
				
			|||
    void init(uint8_t type, uint8_t rot, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t* utcTs, const char* version); | 
				
			|||
    void config(bool enPowerSafe, bool enScreenSaver, uint8_t lum); | 
				
			|||
    void loop(void); | 
				
			|||
    void disp(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod); | 
				
			|||
            IPAddress ip = WiFi.localIP(); | 
				
			|||
            if (!(mExtra % 10) && (ip)) | 
				
			|||
                printText(ip.toString().c_str(), 3); | 
				
			|||
            else if (!(mExtra % 5)) { | 
				
			|||
                snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%d Inverter on", isprod); | 
				
			|||
                printText(mFmtText, 3); | 
				
			|||
            } else if (NULL != mUtcTs) | 
				
			|||
                printText(ah::getTimeStr(gTimezone.toLocal(*mUtcTs)).c_str(), 3); | 
				
			|||
 | 
				
			|||
   private: | 
				
			|||
    void calcLineHeights(); | 
				
			|||
    void setFont(uint8_t line); | 
				
			|||
    void printText(const char* text, uint8_t line); | 
				
			|||
            mDisplay->sendBuffer(); | 
				
			|||
 | 
				
			|||
    U8G2* mDisplay; | 
				
			|||
            mExtra = 1; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
    uint8_t mType; | 
				
			|||
    bool mEnPowerSafe, mEnScreenSaver; | 
				
			|||
    uint8_t mLuminance; | 
				
			|||
    private: | 
				
			|||
        void calcLinePositions() { | 
				
			|||
            uint8_t yOff = 0; | 
				
			|||
            for (uint8_t i = 0; i < 4; i++) { | 
				
			|||
                setFont(i); | 
				
			|||
                yOff += (mDisplay->getMaxCharHeight()); | 
				
			|||
                mLineYOffsets[i] = yOff; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
    uint8_t mLoopCnt; | 
				
			|||
    uint32_t* mUtcTs; | 
				
			|||
    uint8_t mLineOffsets[5]; | 
				
			|||
        inline void setFont(uint8_t line) { | 
				
			|||
            switch (line) { | 
				
			|||
                case 0: | 
				
			|||
                    mDisplay->setFont(u8g2_font_logisoso16_tr); | 
				
			|||
                    break; | 
				
			|||
                case 3: | 
				
			|||
                    mDisplay->setFont(u8g2_font_5x8_tr); | 
				
			|||
                    break; | 
				
			|||
                default: | 
				
			|||
                    mDisplay->setFont(u8g2_font_5x8_tr); | 
				
			|||
                    break; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
    uint16_t _dispY; | 
				
			|||
        void printText(const char *text, uint8_t line) { | 
				
			|||
            uint8_t dispX = (line == 0) ? 10 : 5; | 
				
			|||
            setFont(line); | 
				
			|||
 | 
				
			|||
    uint8_t _mExtra; | 
				
			|||
    uint16_t mTimeout; | 
				
			|||
    char _fmtText[DISP_FMT_TEXT_LEN]; | 
				
			|||
            dispX += (mEnScreenSaver) ? (mExtra % 7) : 0; | 
				
			|||
            mDisplay->drawStr(dispX, mLineYOffsets[line], text); | 
				
			|||
        } | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
					Loading…
					
					
				
		Reference in new issue