Browse Source

Merge branch 'You69Man-feature/PR_display_improvements' into development03

pull/1258/head
lumapu 10 months ago
parent
commit
14b0fbbd68
  1. 6
      src/app.cpp
  2. 2
      src/app.h
  3. 5
      src/appInterface.h
  4. 2
      src/hm/radio.h
  5. 2
      src/hms/hmsRadio.h
  6. 85
      src/plugins/Display/Display.h
  7. 25
      src/plugins/Display/Display_Mono.h
  8. 33
      src/plugins/Display/Display_Mono_128X64.h
  9. 43
      src/plugins/Display/Display_Mono_84X48.h
  10. 4
      src/plugins/Display/Display_data.h
  11. 2
      src/web/RestApi.h
  12. 8
      src/web/html/setup.html
  13. 11
      tools/fonts/u8g2_font_5x8_symbols_ahoy.bdf
  14. 10
      tools/fonts/u8g2_font_5x8_symbols_ahoy.c_
  15. BIN
      tools/fonts/u8g2_font_5x8_symbols_ahoy.fon
  16. 22
      tools/fonts/u8g2_font_ncenB10_symbols10_ahoy.bdf
  17. 14
      tools/fonts/u8g2_font_ncenB10_symbols10_ahoy.c_
  18. BIN
      tools/fonts/u8g2_font_ncenB10_symbols10_ahoy.fon

6
src/app.cpp

@ -86,7 +86,11 @@ void app::setup() {
// Plugins // Plugins
#if defined(PLUGIN_DISPLAY) #if defined(PLUGIN_DISPLAY)
if (mConfig->plugin.display.type != 0) if (mConfig->plugin.display.type != 0)
mDisplay.setup(this, &mConfig->plugin.display, &mSys, &mNrfRadio, &mTimestamp); #if defined(ESP32)
mDisplay.setup(this, &mConfig->plugin.display, &mSys, &mNrfRadio, &mCmtRadio, &mTimestamp);
#else
mDisplay.setup(this, &mConfig->plugin.display, &mSys, &mNrfRadio, NULL, &mTimestamp);
#endif
#endif #endif
mPubSerial.setup(mConfig, &mSys, &mTimestamp); mPubSerial.setup(mConfig, &mSys, &mTimestamp);

2
src/app.h

@ -51,7 +51,7 @@ typedef PubSerial<HmSystemType> PubSerialType;
#if defined(PLUGIN_DISPLAY) #if defined(PLUGIN_DISPLAY)
#include "plugins/Display/Display.h" #include "plugins/Display/Display.h"
#include "plugins/Display/Display_data.h" #include "plugins/Display/Display_data.h"
typedef Display<HmSystemType, HmRadio<>> DisplayType; typedef Display<HmSystemType, Radio> DisplayType;
#endif #endif
class app : public IApp, public ah::Scheduler { class app : public IApp, public ah::Scheduler {

5
src/appInterface.h

@ -53,8 +53,11 @@ class IApp {
virtual bool getSettingsValid() = 0; virtual bool getSettingsValid() = 0;
virtual void setMqttDiscoveryFlag() = 0; virtual void setMqttDiscoveryFlag() = 0;
virtual void setMqttPowerLimitAck(Inverter<> *iv) = 0; virtual void setMqttPowerLimitAck(Inverter<> *iv) = 0;
virtual bool getMqttIsConnected() = 0; virtual bool getMqttIsConnected() = 0;
virtual bool getNrfEnabled() = 0;
virtual bool getCmtEnabled() = 0;
virtual uint32_t getMqttRxCnt() = 0; virtual uint32_t getMqttRxCnt() = 0;
virtual uint32_t getMqttTxCnt() = 0; virtual uint32_t getMqttTxCnt() = 0;

2
src/hm/radio.h

@ -24,6 +24,8 @@ class Radio {
virtual void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) = 0; virtual void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) = 0;
virtual bool switchFrequency(Inverter<> *iv, uint32_t fromkHz, uint32_t tokHz) { return true; } virtual bool switchFrequency(Inverter<> *iv, uint32_t fromkHz, uint32_t tokHz) { return true; }
virtual bool switchFrequencyCh(Inverter<> *iv, uint8_t fromCh, uint8_t toCh) { return true; } virtual bool switchFrequencyCh(Inverter<> *iv, uint8_t fromCh, uint8_t toCh) { return true; }
virtual bool isChipConnected(void) { return false; }
virtual void loop(void) {}; virtual void loop(void) {};
bool get() { bool get() {

2
src/hms/hmsRadio.h

@ -45,7 +45,7 @@ class CmtRadio : public Radio {
} }
} }
bool isConnected() { bool isChipConnected(void) {
return mCmtAvail; return mCmtAvail;
} }

85
src/plugins/Display/Display.h

@ -15,16 +15,17 @@
#include "Display_ePaper.h" #include "Display_ePaper.h"
#include "Display_data.h" #include "Display_data.h"
template <class HMSYSTEM, class HMRADIO> template <class HMSYSTEM, class RADIO>
class Display { class Display {
public: public:
Display() { Display() {
mMono = NULL; mMono = NULL;
} }
void setup(IApp *app, display_t *cfg, HMSYSTEM *sys, HMRADIO *radio, uint32_t *utcTs) { void setup(IApp *app, display_t *cfg, HMSYSTEM *sys, RADIO *hmradio, RADIO *hmsradio, uint32_t *utcTs) {
mApp = app; mApp = app;
mHmRadio = radio; mHmRadio = hmradio;
mHmsRadio = hmsradio;
mCfg = cfg; mCfg = cfg;
mSys = sys; mSys = sys;
mUtcTs = utcTs; mUtcTs = utcTs;
@ -34,13 +35,13 @@ class Display {
mDisplayData.version = app->getVersion(); // version never changes, so only set once mDisplayData.version = app->getVersion(); // version never changes, so only set once
switch (mCfg->type) { switch (mCfg->type) {
case 0: mMono = NULL; break; case 0: mMono = NULL; break; // None
case 1: // fall-through case 1: mMono = new DisplayMono128X64(); break; // SSD1306_128X64 (0.96", 1.54")
case 2: mMono = new DisplayMono128X64(); break; case 2: mMono = new DisplayMono128X64(); break; // SH1106_128X64 (1.3")
case 3: mMono = new DisplayMono84X48(); break; case 3: mMono = new DisplayMono84X48(); break; // PCD8544_84X48 (1.6" - Nokia 5110)
case 4: mMono = new DisplayMono128X32(); break; case 4: mMono = new DisplayMono128X32(); break; // SSD1306_128X32 (0.91")
case 5: mMono = new DisplayMono64X48(); break; case 5: mMono = new DisplayMono64X48(); break; // SSD1306_64X48 (0.66" - Wemos OLED Shield)
case 6: mMono = new DisplayMono128X64(); break; case 6: mMono = new DisplayMono128X64(); break; // SSD1309_128X64 (2.42")
#if defined(ESP32) #if defined(ESP32)
case 10: case 10:
mMono = NULL; // ePaper does not use this mMono = NULL; // ePaper does not use this
@ -92,9 +93,9 @@ class Display {
if (mCfg->type == 0) if (mCfg->type == 0)
return; return;
float totalPower = 0; float totalPower = 0.0;
float totalYieldDay = 0; float totalYieldDay = 0.0;
float totalYieldTotal = 0; float totalYieldTotal = 0.0;
uint8_t nrprod = 0; uint8_t nrprod = 0;
uint8_t nrsleep = 0; uint8_t nrsleep = 0;
@ -109,42 +110,53 @@ class Display {
if (iv == NULL) if (iv == NULL)
continue; continue;
int8_t maxQInv = -6; if (iv->isProducing()) // also updates inverter state engine
for(uint8_t ch = 0; ch < RF_MAX_CHANNEL_ID; ch++) {
int8_t q = iv->txRfQuality[ch];
if (q > maxQInv)
maxQInv = q;
}
if (maxQInv < minQAllInv)
minQAllInv = maxQInv;
rec = iv->getRecordStruct(RealTimeRunData_Debug);
if (iv->isProducing())
nrprod++; nrprod++;
else else
nrsleep++; nrsleep++;
totalPower += iv->getChannelFieldValue(CH0, FLD_PAC, rec); rec = iv->getRecordStruct(RealTimeRunData_Debug);
totalYieldDay += iv->getChannelFieldValue(CH0, FLD_YD, rec);
totalYieldTotal += iv->getChannelFieldValue(CH0, FLD_YT, rec);
if(allOff) { if (iv->isAvailable()) { // consider only radio quality of inverters still communicating
if(iv->status != InverterStatus::OFF) int8_t maxQInv = -6;
allOff = false; for(uint8_t ch = 0; ch < RF_MAX_CHANNEL_ID; ch++) {
int8_t q = iv->txRfQuality[ch];
if (q > maxQInv)
maxQInv = q;
}
if (maxQInv < minQAllInv)
minQAllInv = maxQInv;
totalPower += iv->getChannelFieldValue(CH0, FLD_PAC, rec); // add only FLD_PAC from inverters still communicating
allOff = false;
} }
totalYieldDay += iv->getChannelFieldValue(CH0, FLD_YD, rec);
totalYieldTotal += iv->getChannelFieldValue(CH0, FLD_YT, rec);
} }
if (allOff)
minQAllInv = -6;
// prepare display data // prepare display data
mDisplayData.nrProducing = nrprod; mDisplayData.nrProducing = nrprod;
mDisplayData.nrSleeping = nrsleep; mDisplayData.nrSleeping = nrsleep;
mDisplayData.totalPower = (allOff) ? 0.0 : totalPower; // if all inverters are off, total power can't be greater than 0 mDisplayData.totalPower = totalPower;
mDisplayData.totalYieldDay = totalYieldDay; mDisplayData.totalYieldDay = totalYieldDay;
mDisplayData.totalYieldTotal = totalYieldTotal; mDisplayData.totalYieldTotal = totalYieldTotal;
mDisplayData.RadioSymbol = mHmRadio->isChipConnected(); bool nrf_en = mApp->getNrfEnabled();
bool nrf_ok = nrf_en && mHmRadio->isChipConnected();
#if defined(ESP32)
bool cmt_en = mApp->getCmtEnabled();
bool cmt_ok = cmt_en && mHmsRadio->isChipConnected();
#else
bool cmt_en = false;
bool cmt_ok = false;
#endif
mDisplayData.RadioSymbol = (nrf_ok && !cmt_en) || (cmt_ok && !nrf_en) || (nrf_ok && cmt_ok);
mDisplayData.WifiSymbol = (WiFi.status() == WL_CONNECTED); mDisplayData.WifiSymbol = (WiFi.status() == WL_CONNECTED);
mDisplayData.MQTTSymbol = mApp->getMqttIsConnected(); mDisplayData.MQTTSymbol = mApp->getMqttIsConnected();
mDisplayData.RadioRSSI = (0 < mDisplayData.nrProducing) ? ivQuality2RadioRSSI(minQAllInv) : SCHAR_MIN; // Workaround as NRF24 has no RSSI. Approximation by quality levels from heuristic function mDisplayData.RadioRSSI = ivQuality2RadioRSSI(minQAllInv); // Workaround as NRF24 has no RSSI. Approximation by quality levels from heuristic function
mDisplayData.WifiRSSI = (WiFi.status() == WL_CONNECTED) ? WiFi.RSSI() : SCHAR_MIN; mDisplayData.WifiRSSI = (WiFi.status() == WL_CONNECTED) ? WiFi.RSSI() : SCHAR_MIN;
mDisplayData.ipAddress = WiFi.localIP(); mDisplayData.ipAddress = WiFi.localIP();
time_t utc= mApp->getTimestamp(); time_t utc= mApp->getTimestamp();
@ -158,7 +170,7 @@ class Display {
} }
#if defined(ESP32) #if defined(ESP32)
else if (mCfg->type == 10) { else if (mCfg->type == 10) {
mEpaper.loop(((allOff) ? 0.0 : totalPower), totalYieldDay, totalYieldTotal, nrprod); mEpaper.loop((totalPower), totalYieldDay, totalYieldTotal, nrprod);
mRefreshCycle++; mRefreshCycle++;
} }
@ -212,7 +224,8 @@ class Display {
uint32_t *mUtcTs; uint32_t *mUtcTs;
display_t *mCfg; display_t *mCfg;
HMSYSTEM *mSys; HMSYSTEM *mSys;
HMRADIO *mHmRadio; RADIO *mHmRadio;
RADIO *mHmsRadio;
uint16_t mRefreshCycle; uint16_t mRefreshCycle;
#if defined(ESP32) #if defined(ESP32)

25
src/plugins/Display/Display_Mono.h

@ -114,8 +114,8 @@ Symbols:
\x87 ... moon \x87 ... moon
\x88 ... calendar/day \x88 ... calendar/day
\x89 ... MQTT */ \x89 ... MQTT */
const uint8_t u8g2_font_5x8_symbols_ahoy[1052] U8G2_FONT_SECTION("u8g2_font_5x8_symbols_ahoy") = const uint8_t u8g2_font_5x8_symbols_ahoy[1049] U8G2_FONT_SECTION("u8g2_font_5x8_symbols_ahoy") =
"j\0\3\2\4\4\3\4\5\10\10\0\377\6\377\6\0\1\61\2b\4\3 \5\0\304\11!\7a\306" "j\0\3\2\4\4\3\4\5\10\10\0\377\6\377\6\0\1\61\2b\4\0 \5\0\304\11!\7a\306"
"\212!\11\42\7\63\335\212\304\22#\16u\304\232R\222\14JePJI\2$\14u\304\252l\251m" "\212!\11\42\7\63\335\212\304\22#\16u\304\232R\222\14JePJI\2$\14u\304\252l\251m"
"I\262E\0%\10S\315\212(\351\24&\13t\304\232(i\252\64%\1'\6\61\336\212\1(\7b" "I\262E\0%\10S\315\212(\351\24&\13t\304\232(i\252\64%\1'\6\61\336\212\1(\7b"
"\305\32\245))\11b\305\212(\251(\0*\13T\304\212(Q\206D\211\2+\12U\304\252\60\32\244" "\305\32\245))\11b\305\212(\251(\0*\13T\304\212(Q\206D\211\2+\12U\304\252\60\32\244"
@ -145,9 +145,10 @@ const uint8_t u8g2_font_5x8_symbols_ahoy[1052] U8G2_FONT_SECTION("u8g2_font_5x8_
"\0z\11D\304\212!*\15\1{\12t\304*%L\304(\24|\6a\306\212\3}\13t\304\12\61" "\0z\11D\304\212!*\15\1{\12t\304*%L\304(\24|\6a\306\212\3}\13t\304\12\61"
"\12\225\60\221\0~\10$\344\232DI\0\5\0\304\12\200\13u\274\212K\242T\266\260\4\201\14f" "\12\225\60\221\0~\10$\344\232DI\0\5\0\304\12\200\13u\274\212K\242T\266\260\4\201\14f"
"D\233!\11#-\312!\11\202\15hD<\65\12\243,\214\302$\16\203\15w<\214C\22F\71\220" "D\233!\11#-\312!\11\202\15hD<\65\12\243,\214\302$\16\203\15w<\214C\22F\71\220"
"\26\207A\204\16\205\274\212,)%Y\230%QR\13\205\17\206<\213\60\31\22\311\66D\245!\11\3" "\26\207A\204\13u\274\212\244\232t\313\241\10\205\17\206<\213\60\31\22\311\66D\245!\11\3\206\20\210"
"\206\20\210<\254\342\20]\302(L\246C\30E\0\207\15wD\334X\25\267\341\20\15\21\0\210\16w" "<\254\342\20]\302(L\246C\30E\0\207\15wD\334X\25\267\341\20\15\21\0\210\16w<\214\203"
"<\214\203RQ\25I\212\324a\20\211\15f\304\213)\213\244,\222\222\245\0\0\0\0"; "RQ\25I\212\324a\20\211\15f\304\213)\213\244,\222\222\245\0\0\0\0";
const uint8_t u8g2_font_ncenB08_symbols8_ahoy[173] U8G2_FONT_SECTION("u8g2_font_ncenB08_symbols8_ahoy") = const uint8_t u8g2_font_ncenB08_symbols8_ahoy[173] U8G2_FONT_SECTION("u8g2_font_ncenB08_symbols8_ahoy") =
"\13\0\3\2\4\4\1\2\5\10\11\0\0\10\0\10\0\0\0\0\0\0\224A\14\207\305\70H\321\222H" "\13\0\3\2\4\4\1\2\5\10\11\0\0\10\0\10\0\0\0\0\0\0\224A\14\207\305\70H\321\222H"
@ -157,11 +158,11 @@ const uint8_t u8g2_font_ncenB08_symbols8_ahoy[173] U8G2_FONT_SECTION("u8g2_font_
"Q\4H\14w\307\215Uq\33\16\321\20\1I\21\227\305\311\222aP\245H\221\244H\212\324a\20J" "Q\4H\14w\307\215Uq\33\16\321\20\1I\21\227\305\311\222aP\245H\221\244H\212\324a\20J"
"\5\0\275\0K\5\0\315\0\0\0\0"; "\5\0\275\0K\5\0\315\0\0\0\0";
const uint8_t u8g2_font_ncenB10_symbols10_ahoy[220] U8G2_FONT_SECTION("u8g2_font_ncenB10_symbols10_ahoy") = const uint8_t u8g2_font_ncenB10_symbols10_ahoy[217] U8G2_FONT_SECTION("u8g2_font_ncenB10_symbols10_ahoy") =
"\13\0\3\2\4\4\2\2\5\13\13\0\0\13\0\13\0\0\0\0\0\0\303A\15\267\212q\220\42\251\322" "\13\0\3\2\4\4\2\2\5\13\13\0\0\13\0\13\0\0\0\0\0\0\300A\15\267\212q\220\42\251\322"
"\266\306\275\1B\20\230\236\65da\22Ima\250F\71\254\1C\23\272\272\251\3Q\32\366Q\212\243" "\266\306\275\1B\20\230\236\65da\22Ima\250F\71\254\1C\23\272\272\251\3Q\32\366Q\212\243"
"\70\212\243\70\311\221\0D\20\271\252\361\242F:\242#: {\36\16\1E\22\267\212\361\222\14I\242" "\70\212\243\70\311\221\0D\20\271\252\361\242F:\242#: {\36\16\1E\17\267\212\221\264\3Q\35"
"\14\332\232\216[RJ\232\12F\25\250\233\221\14I\61I\206$\252%J\250Fa\224%J\71G\30" "\332\321\34\316\341\14F\25\250\233\221\14I\61I\206$\252%J\250Fa\224%J\71G\30\273\312W"
"\273\312W\316r`T\262DJ\303\64L#%K\304\35\310\342,\3H\27\272\272\217\344P\16\351\210" "\316r`T\262DJ\303\64L#%K\304\35\310\342,\3H\27\272\272\217\344P\16\351\210\16\354\300"
"\16\354\300<\244C\70,\303 \16!\0I\24\271\252\241\34\336\1-\223\64-\323\62-\323\62\35x" "<\244C\70,\303 \16!\0I\24\271\252\241\34\336\1-\223\64-\323\62-\323\62\35x\10J\22"
"\10J\22\210\232\61Hi\64Di\64DI\226$KeiK\5\0\232\1\0\0\0"; "\210\232\61Hi\64Di\64DI\226$KeiK\5\0\212\1\0\0\0";

33
src/plugins/Display/Display_Mono_128X64.h

@ -49,9 +49,9 @@ class DisplayMono128X64 : public DisplayMono {
/* /*
mDisplayData->nrSleeping = 10; mDisplayData->nrSleeping = 10;
mDisplayData->nrProducing = 10; mDisplayData->nrProducing = 10;
mDisplayData->totalPower = 99990; mDisplayData->totalPower = 54321.9; // W
mDisplayData->totalYieldDay = 8888; mDisplayData->totalYieldDay = 4321.9; // Wh
mDisplayData->totalYieldTotal = 9999; mDisplayData->totalYieldTotal = 4321.9; // kWh
mDisplay->drawPixel(0, 0); mDisplay->drawPixel(0, 0);
mDisplay->drawPixel(mDispWidth-1, 0); mDisplay->drawPixel(mDispWidth-1, 0);
mDisplay->drawPixel(0, mDispHeight-1); mDisplay->drawPixel(0, mDispHeight-1);
@ -64,9 +64,10 @@ class DisplayMono128X64 : public DisplayMono {
// print total power // print total power
if (mDisplayData->nrProducing > 0) { if (mDisplayData->nrProducing > 0) {
if (mDisplayData->totalPower > 999) if (mDisplayData->totalPower > 999)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.2f kW", (mDisplayData->totalPower / 1000)); snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.1f kW", (mDisplayData->totalPower / 1000.0));
else else
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.0f W", mDisplayData->totalPower); snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.0f W", mDisplayData->totalPower);
printText(mFmtText, l_TotalPower, 0xff); printText(mFmtText, l_TotalPower, 0xff);
} else { } else {
printText("offline", l_TotalPower, 0xff); printText("offline", l_TotalPower, 0xff);
@ -109,19 +110,27 @@ class DisplayMono128X64 : public DisplayMono {
pos = (mDispWidth - mDisplay->getStrWidth(mFmtText)) / 2; pos = (mDispWidth - mDisplay->getStrWidth(mFmtText)) / 2;
mDisplay->setFont(u8g2_font_ncenB08_symbols8_ahoy); mDisplay->setFont(u8g2_font_ncenB08_symbols8_ahoy);
if (sun_pos!=-1) if (sun_pos!=-1)
mDisplay->drawStr(pos + sun_pos + mPixelshift, mLineYOffsets[l_Status], "G"); // sun mDisplay->drawStr(pos + sun_pos + mPixelshift, mLineYOffsets[l_Status], "G"); // sun symbol
if (moon_pos!=-1) if (moon_pos!=-1)
mDisplay->drawStr(pos + moon_pos + mPixelshift, mLineYOffsets[l_Status], "H"); // moon mDisplay->drawStr(pos + moon_pos + mPixelshift, mLineYOffsets[l_Status], "H"); // moon symbol
} }
// print yields // print yields
mDisplay->setFont(u8g2_font_ncenB10_symbols10_ahoy); mDisplay->setFont(u8g2_font_ncenB10_symbols10_ahoy);
mDisplay->drawStr(17 + mPixelshift, mLineYOffsets[l_YieldDay], "I"); // day mDisplay->drawStr(16 + mPixelshift, mLineYOffsets[l_YieldDay], "I"); // day symbol
mDisplay->drawStr(17 + mPixelshift, mLineYOffsets[l_YieldTotal], "D"); // total mDisplay->drawStr(16 + mPixelshift, mLineYOffsets[l_YieldTotal], "D"); // total symbol
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%7.0f Wh", mDisplayData->totalYieldDay);
printText(mFmtText, l_YieldDay, 25); if (mDisplayData->totalYieldDay > 999.0)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%7.1f kWh", mDisplayData->totalYieldTotal); snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.1f kWh", mDisplayData->totalYieldDay / 1000.0);
printText(mFmtText, l_YieldTotal, 25); else
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.0f Wh", mDisplayData->totalYieldDay);
printText(mFmtText, l_YieldDay, 0xff);
if (mDisplayData->totalYieldTotal > 999.0)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.1f MWh", mDisplayData->totalYieldTotal / 1000.0);
else
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.1f kWh", mDisplayData->totalYieldTotal);
printText(mFmtText, l_YieldTotal, 0xff);
// draw dynamic RSSI bars // draw dynamic RSSI bars
int xoffs; int xoffs;

43
src/plugins/Display/Display_Mono_84X48.h

@ -34,12 +34,11 @@ class DisplayMono84X48 : public DisplayMono {
// Layout-Test // Layout-Test
/* /*
mDisplayData->nrSleeping = 0; mDisplayData->nrSleeping = 10;
mDisplayData->nrProducing = 1; mDisplayData->nrProducing = 10;
mDisplayData->totalPower = 12345.67; mDisplayData->totalPower = 111.91; // W
mDisplayData->totalYieldDay = 12345.67; mDisplayData->totalYieldDay = 54321.9; // Wh
mDisplayData->totalYieldTotal = 1234; mDisplayData->totalYieldTotal = 654321.9; // kWh
mDisplayData->utcTs += 1000000;
mDisplay->drawPixel(0, 0); mDisplay->drawPixel(0, 0);
mDisplay->drawPixel(mDispWidth-1, 0); mDisplay->drawPixel(mDispWidth-1, 0);
mDisplay->drawPixel(0, mDispHeight-1); mDisplay->drawPixel(0, mDispHeight-1);
@ -48,12 +47,10 @@ class DisplayMono84X48 : public DisplayMono {
// print total power // print total power
if (mDisplayData->nrProducing > 0) { if (mDisplayData->nrProducing > 0) {
if (mDisplayData->totalPower > 9999) if (mDisplayData->totalPower > 999)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.2fkW", (mDisplayData->totalPower / 1000)); // forgo spacing between value and SI unit in favor of second position after decimal point snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.1f kW", (mDisplayData->totalPower / 1000));
else if (mDisplayData->totalPower > 999)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.2f kW", (mDisplayData->totalPower / 1000));
else else
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.1f W", mDisplayData->totalPower); snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.0f W", mDisplayData->totalPower);
printText(mFmtText, l_TotalPower, 0xff); printText(mFmtText, l_TotalPower, 0xff);
} else { } else {
@ -75,21 +72,29 @@ class DisplayMono84X48 : public DisplayMono {
if (0 == mDisplayData->nrSleeping + mDisplayData->nrProducing) if (0 == mDisplayData->nrSleeping + mDisplayData->nrProducing)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "no inverter"); snprintf(mFmtText, DISP_FMT_TEXT_LEN, "no inverter");
else if (0 == mDisplayData->nrSleeping) else if (0 == mDisplayData->nrSleeping)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "\x86"); snprintf(mFmtText, DISP_FMT_TEXT_LEN, "\x86"); // sun symbol
else if (0 == mDisplayData->nrProducing) else if (0 == mDisplayData->nrProducing)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "\x87"); snprintf(mFmtText, DISP_FMT_TEXT_LEN, "\x87"); // moon symbol
else else
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%d\x86 %d\x87", mDisplayData->nrProducing, mDisplayData->nrSleeping); snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%d\x86 %d\x87", mDisplayData->nrProducing, mDisplayData->nrSleeping);
printText(mFmtText, l_Status, 0xff); printText(mFmtText, l_Status, 0xff);
} }
// print yields // print yields
printText("\x88", l_YieldDay, 11); // day symbol printText("\x88", l_YieldDay, 10); // day symbol
printText("\x83", l_YieldTotal, 11); // total symbol printText("\x83", l_YieldTotal, 10); // total symbol
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%7.0f Wh", mDisplayData->totalYieldDay);
printText(mFmtText, l_YieldDay, 18); if (mDisplayData->totalYieldDay > 999.0)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%7.1f kWh", mDisplayData->totalYieldTotal); snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.1f kWh", mDisplayData->totalYieldDay / 1000.0);
printText(mFmtText, l_YieldTotal, 18); else
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.0f Wh", mDisplayData->totalYieldDay);
printText(mFmtText, l_YieldDay, 0xff);
if (mDisplayData->totalYieldTotal > 999.0)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.1f MWh", mDisplayData->totalYieldTotal / 1000.0);
else
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.1f kWh", mDisplayData->totalYieldTotal);
printText(mFmtText, l_YieldTotal, 0xff);
// draw dynamic Nokia RSSI bars // draw dynamic Nokia RSSI bars
int rssi_bar_height = 7; int rssi_bar_height = 7;

4
src/plugins/Display/Display_data.h

@ -6,8 +6,8 @@
struct DisplayData { struct DisplayData {
const char *version=nullptr; const char *version=nullptr;
float totalPower=0.0f; // indicate current power (W) float totalPower=0.0f; // indicate current power (W)
float totalYieldDay=0.0f; // indicate day yield (W) float totalYieldDay=0.0f; // indicate day yield (Wh)
float totalYieldTotal=0.0f; // indicate total yield (W) float totalYieldTotal=0.0f; // indicate total yield (kWh)
uint32_t utcTs=0; // indicate absolute timestamp (utc unix time). 0 = time is not synchonized uint32_t utcTs=0; // indicate absolute timestamp (utc unix time). 0 = time is not synchonized
uint8_t nrProducing=0; // indicate number of producing inverters uint8_t nrProducing=0; // indicate number of producing inverters
uint8_t nrSleeping=0; // indicate number of sleeping inverters uint8_t nrSleeping=0; // indicate number of sleeping inverters

2
src/web/RestApi.h

@ -547,7 +547,7 @@ class RestApi {
void getRadioCmtInfo(JsonObject obj) { void getRadioCmtInfo(JsonObject obj) {
obj[F("en")] = (bool) mConfig->cmt.enabled; obj[F("en")] = (bool) mConfig->cmt.enabled;
obj[F("isconnected")] = mRadioCmt->isConnected(); obj[F("isconnected")] = mRadioCmt->isChipConnected();
obj[F("sn")] = String(mRadioCmt->getDTUSn(), HEX); obj[F("sn")] = String(mRadioCmt->getDTUSn(), HEX);
} }
#endif #endif

8
src/web/html/setup.html

@ -964,7 +964,13 @@
); );
} }
// keep display types grouped // keep display types grouped
var opts = [[0, "None"], [2, "SH1106 1.3\" 128X64"], [5, "SSD1306 0.66\" 64X48 (Wemos OLED Shield)"], [4, "SSD1306 0.91\" 128X32"], [1, "SSD1306 0.96\" 128X64"], [6, "SSD1309 2.42\" 128X64"], [3, "Nokia5110"]]; var opts = [[0, "None"],
[2, "SH1106 128x64 (1.3\")"],
[5, "SSD1306 64x48 (0.66\" Wemos OLED Shield)"],
[4, "SSD1306 128x32 (0.91\")"],
[1, "SSD1306 128x64 (0.96\", 1.54\")"],
[6, "SSD1309 128X64 (2.42\")"],
[3, "PCD8544 84X48 (1.6\" Nokia 5110)"]];
/*IF_ESP32*/ /*IF_ESP32*/
opts.push([10, "ePaper"]); opts.push([10, "ePaper"]);
/*ENDIF_ESP32*/ /*ENDIF_ESP32*/

11
tools/fonts/u8g2_font_5x8_symbols_ahoy.bdf

@ -1243,16 +1243,15 @@ STARTCHAR 132
ENCODING 132 ENCODING 132
SWIDTH 360 0 SWIDTH 360 0
DWIDTH 5 0 DWIDTH 5 0
BBX 5 8 0 -1 BBX 5 7 0 -1
BITMAP BITMAP
88 A8
50 00
A8
50 50
20 20
00
20 20
50
50
88
ENDCHAR ENDCHAR
STARTCHAR 133 STARTCHAR 133
ENCODING 133 ENCODING 133

10
tools/fonts/u8g2_font_5x8_symbols_ahoy.c_

@ -4,8 +4,8 @@
Glyphs: 106/106 Glyphs: 106/106
BBX Build Mode: 0 BBX Build Mode: 0
*/ */
const uint8_t u8g2_font_5x8_symbols_ahoy[1052] U8G2_FONT_SECTION("u8g2_font_5x8_symbols_ahoy") = const uint8_t u8g2_font_5x8_symbols_ahoy[1049] U8G2_FONT_SECTION("u8g2_font_5x8_symbols_ahoy") =
"j\0\3\2\4\4\3\4\5\10\10\0\377\6\377\6\0\1\61\2b\4\3 \5\0\304\11!\7a\306" "j\0\3\2\4\4\3\4\5\10\10\0\377\6\377\6\0\1\61\2b\4\0 \5\0\304\11!\7a\306"
"\212!\11\42\7\63\335\212\304\22#\16u\304\232R\222\14JePJI\2$\14u\304\252l\251m" "\212!\11\42\7\63\335\212\304\22#\16u\304\232R\222\14JePJI\2$\14u\304\252l\251m"
"I\262E\0%\10S\315\212(\351\24&\13t\304\232(i\252\64%\1'\6\61\336\212\1(\7b" "I\262E\0%\10S\315\212(\351\24&\13t\304\232(i\252\64%\1'\6\61\336\212\1(\7b"
"\305\32\245))\11b\305\212(\251(\0*\13T\304\212(Q\206D\211\2+\12U\304\252\60\32\244" "\305\32\245))\11b\305\212(\251(\0*\13T\304\212(Q\206D\211\2+\12U\304\252\60\32\244"
@ -35,6 +35,6 @@ const uint8_t u8g2_font_5x8_symbols_ahoy[1052] U8G2_FONT_SECTION("u8g2_font_5x8_
"\0z\11D\304\212!*\15\1{\12t\304*%L\304(\24|\6a\306\212\3}\13t\304\12\61" "\0z\11D\304\212!*\15\1{\12t\304*%L\304(\24|\6a\306\212\3}\13t\304\12\61"
"\12\225\60\221\0~\10$\344\232DI\0\5\0\304\12\200\13u\274\212K\242T\266\260\4\201\14f" "\12\225\60\221\0~\10$\344\232DI\0\5\0\304\12\200\13u\274\212K\242T\266\260\4\201\14f"
"D\233!\11#-\312!\11\202\15hD<\65\12\243,\214\302$\16\203\15w<\214C\22F\71\220" "D\233!\11#-\312!\11\202\15hD<\65\12\243,\214\302$\16\203\15w<\214C\22F\71\220"
"\26\207A\204\16\205\274\212,)%Y\230%QR\13\205\17\206<\213\60\31\22\311\66D\245!\11\3" "\26\207A\204\13u\274\212\244\232t\313\241\10\205\17\206<\213\60\31\22\311\66D\245!\11\3\206\20\210"
"\206\20\210<\254\342\20]\302(L\246C\30E\0\207\15wD\334X\25\267\341\20\15\21\0\210\16w" "<\254\342\20]\302(L\246C\30E\0\207\15wD\334X\25\267\341\20\15\21\0\210\16w<\214\203"
"<\214\203RQ\25I\212\324a\20\211\15f\304\213)\213\244,\222\222\245\0\0\0\0"; "RQ\25I\212\324a\20\211\15f\304\213)\213\244,\222\222\245\0\0\0\0";

BIN
tools/fonts/u8g2_font_5x8_symbols_ahoy.fon

Binary file not shown.

22
tools/fonts/u8g2_font_ncenB10_symbols10_ahoy.bdf

@ -88,17 +88,17 @@ SWIDTH 576 0
DWIDTH 8 0 DWIDTH 8 0
BBX 7 11 0 0 BBX 7 11 0 0
BITMAP BITMAP
FE AA
D6 00
D6 92
7C 00
38 38
00
10
00
10
00
10 10
38
38
54
54
92
ENDCHAR ENDCHAR
STARTCHAR 070 STARTCHAR 070
ENCODING 70 ENCODING 70
@ -188,8 +188,8 @@ D5
ENDCHAR ENDCHAR
STARTCHAR 075 STARTCHAR 075
ENCODING 75 ENCODING 75
SWIDTH 648 0 SWIDTH 576 0
DWIDTH 9 0 DWIDTH 8 0
BBX 0 0 0 0 BBX 0 0 0 0
BITMAP BITMAP
ENDCHAR ENDCHAR

14
tools/fonts/u8g2_font_ncenB10_symbols10_ahoy.c_

@ -4,11 +4,11 @@
Glyphs: 11/11 Glyphs: 11/11
BBX Build Mode: 0 BBX Build Mode: 0
*/ */
const uint8_t u8g2_font_ncenB10_symbols10_ahoy[220] U8G2_FONT_SECTION("u8g2_font_ncenB10_symbols10_ahoy") = const uint8_t u8g2_font_ncenB10_symbols10_ahoy[217] U8G2_FONT_SECTION("u8g2_font_ncenB10_symbols10_ahoy") =
"\13\0\3\2\4\4\2\2\5\13\13\0\0\13\0\13\0\0\0\0\0\0\303A\15\267\212q\220\42\251\322" "\13\0\3\2\4\4\2\2\5\13\13\0\0\13\0\13\0\0\0\0\0\0\300A\15\267\212q\220\42\251\322"
"\266\306\275\1B\20\230\236\65da\22Ima\250F\71\254\1C\23\272\272\251\3Q\32\366Q\212\243" "\266\306\275\1B\20\230\236\65da\22Ima\250F\71\254\1C\23\272\272\251\3Q\32\366Q\212\243"
"\70\212\243\70\311\221\0D\20\271\252\361\242F:\242#: {\36\16\1E\22\267\212\361\222\14I\242" "\70\212\243\70\311\221\0D\20\271\252\361\242F:\242#: {\36\16\1E\17\267\212\221\264\3Q\35"
"\14\332\232\216[RJ\232\12F\25\250\233\221\14I\61I\206$\252%J\250Fa\224%J\71G\30" "\332\321\34\316\341\14F\25\250\233\221\14I\61I\206$\252%J\250Fa\224%J\71G\30\273\312W"
"\273\312W\316r`T\262DJ\303\64L#%K\304\35\310\342,\3H\27\272\272\217\344P\16\351\210" "\316r`T\262DJ\303\64L#%K\304\35\310\342,\3H\27\272\272\217\344P\16\351\210\16\354\300"
"\16\354\300<\244C\70,\303 \16!\0I\24\271\252\241\34\336\1-\223\64-\323\62-\323\62\35x" "<\244C\70,\303 \16!\0I\24\271\252\241\34\336\1-\223\64-\323\62-\323\62\35x\10J\22"
"\10J\22\210\232\61Hi\64Di\64DI\226$KeiK\5\0\232\1\0\0\0"; "\210\232\61Hi\64Di\64DI\226$KeiK\5\0\212\1\0\0\0";

BIN
tools/fonts/u8g2_font_ncenB10_symbols10_ahoy.fon

Binary file not shown.
Loading…
Cancel
Save