mirror of https://github.com/lumapu/ahoy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
229 lines
9.3 KiB
229 lines
9.3 KiB
//-----------------------------------------------------------------------------
|
|
// 2023 Ahoy, https://ahoydtu.de
|
|
// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#pragma once
|
|
#include "Display_Mono.h"
|
|
|
|
class DisplayMono128X64 : public DisplayMono {
|
|
public:
|
|
DisplayMono128X64() : DisplayMono() {
|
|
mExtra = 0;
|
|
}
|
|
|
|
void config(bool enPowerSave, uint8_t screenSaver, uint8_t lum) {
|
|
mEnPowerSave = enPowerSave;
|
|
mScreenSaver = screenSaver;
|
|
mLuminance = lum;
|
|
}
|
|
|
|
void init(uint8_t type, uint8_t rotation, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, DisplayData *displayData) {
|
|
u8g2_cb_t *rot = (u8g2_cb_t *)((rotation != 0x00) ? U8G2_R2 : U8G2_R0);
|
|
switch (type) {
|
|
case 1:
|
|
monoInit(new U8G2_SSD1306_128X64_NONAME_F_HW_I2C(rot, reset, clock, data), type, displayData);
|
|
break;
|
|
case 2:
|
|
monoInit(new U8G2_SH1106_128X64_NONAME_F_HW_I2C(rot, reset, clock, data), type, displayData);
|
|
break;
|
|
case 6:
|
|
default:
|
|
monoInit(new U8G2_SSD1309_128X64_NONAME0_F_HW_I2C(rot, reset, clock, data), type, displayData);
|
|
break;
|
|
}
|
|
calcLinePositions();
|
|
|
|
printText("Ahoy!", l_Ahoy, 0xff);
|
|
printText("ahoydtu.de", l_Website, 0xff);
|
|
printText(mDisplayData->version, l_Version, 0xff);
|
|
mDisplay->sendBuffer();
|
|
}
|
|
|
|
void disp(void) {
|
|
uint8_t pos, sun_pos, moon_pos;
|
|
|
|
mDisplay->clearBuffer();
|
|
|
|
// Layout-Test
|
|
/*
|
|
mDisplayData->nrSleeping = 10;
|
|
mDisplayData->nrProducing = 10;
|
|
mDisplayData->totalPower = 15432.9; // W
|
|
mDisplayData->totalYieldDay = 14321.9; // Wh
|
|
mDisplayData->totalYieldTotal = 15432.9; // kWh
|
|
mDisplay->drawPixel(0, 0);
|
|
mDisplay->drawPixel(mDispWidth-1, 0);
|
|
mDisplay->drawPixel(0, mDispHeight-1);
|
|
mDisplay->drawPixel(mDispWidth-1, mDispHeight-1);
|
|
*/
|
|
|
|
// calculate current pixelshift for pixelshift screensaver
|
|
calcPixelShift(pixelShiftRange);
|
|
|
|
// print total power
|
|
if (mDisplayData->nrProducing > 0) {
|
|
if (mDisplayData->totalPower > 9999.0)
|
|
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.2f kW", (mDisplayData->totalPower / 1000.0));
|
|
else
|
|
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.0f W", mDisplayData->totalPower);
|
|
|
|
printText(mFmtText, l_TotalPower, 0xff);
|
|
} else {
|
|
printText("offline", l_TotalPower, 0xff);
|
|
}
|
|
|
|
// print Date and time
|
|
if (0 != mDisplayData->utcTs)
|
|
printText(ah::getDateTimeStrShort(gTimezone.toLocal(mDisplayData->utcTs)).c_str(), l_Time, 0xff);
|
|
|
|
// dynamic status bar, alternatively:
|
|
// print ip address
|
|
if (!(mExtra % 5) && (mDisplayData->ipAddress)) {
|
|
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%s", (mDisplayData->ipAddress).toString().c_str());
|
|
printText(mFmtText, l_Status, 0xff);
|
|
}
|
|
// print status of inverters
|
|
else {
|
|
sun_pos = -1;
|
|
moon_pos = -1;
|
|
setLineFont(l_Status);
|
|
if (0 == mDisplayData->nrSleeping + mDisplayData->nrProducing)
|
|
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "no inverter");
|
|
else if (0 == mDisplayData->nrSleeping) {
|
|
snprintf(mFmtText, DISP_FMT_TEXT_LEN, " ");
|
|
sun_pos = 0;
|
|
}
|
|
else if (0 == mDisplayData->nrProducing) {
|
|
snprintf(mFmtText, DISP_FMT_TEXT_LEN, " ");
|
|
moon_pos = 0;
|
|
}
|
|
else {
|
|
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%2d", mDisplayData->nrProducing);
|
|
sun_pos = mDisplay->getStrWidth(mFmtText) + 1;
|
|
snprintf(mFmtText+2, DISP_FMT_TEXT_LEN, " %2d", mDisplayData->nrSleeping);
|
|
moon_pos = mDisplay->getStrWidth(mFmtText) + 1;
|
|
snprintf(mFmtText+7, DISP_FMT_TEXT_LEN, " ");
|
|
}
|
|
printText(mFmtText, l_Status, 0xff);
|
|
|
|
pos = (mDispWidth - mDisplay->getStrWidth(mFmtText)) / 2;
|
|
mDisplay->setFont(u8g2_font_ncenB08_symbols8_ahoy);
|
|
if (sun_pos!=-1)
|
|
mDisplay->drawStr(pos + sun_pos + mPixelshift, mLineYOffsets[l_Status], "G"); // sun symbol
|
|
if (moon_pos!=-1)
|
|
mDisplay->drawStr(pos + moon_pos + mPixelshift, mLineYOffsets[l_Status], "H"); // moon symbol
|
|
}
|
|
|
|
// print yields
|
|
mDisplay->setFont(u8g2_font_ncenB10_symbols10_ahoy);
|
|
mDisplay->drawStr(16 + mPixelshift, mLineYOffsets[l_YieldDay], "I"); // day symbol
|
|
mDisplay->drawStr(16 + mPixelshift, mLineYOffsets[l_YieldTotal], "D"); // total symbol
|
|
|
|
if (mDisplayData->totalYieldDay > 9999.0)
|
|
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.2f kWh", mDisplayData->totalYieldDay / 1000.0);
|
|
else
|
|
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.0f Wh", mDisplayData->totalYieldDay);
|
|
printText(mFmtText, l_YieldDay, 0xff);
|
|
|
|
if (mDisplayData->totalYieldTotal > 9999.0)
|
|
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.2f MWh", mDisplayData->totalYieldTotal / 1000.0);
|
|
else
|
|
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.0f kWh", mDisplayData->totalYieldTotal);
|
|
printText(mFmtText, l_YieldTotal, 0xff);
|
|
|
|
// draw dynamic RSSI bars
|
|
int xoffs;
|
|
if (mScreenSaver == 1) // shrink screenwidth for pixelshift screensaver
|
|
xoffs = pixelShiftRange/2;
|
|
else
|
|
xoffs = 0;
|
|
int rssi_bar_height = 9;
|
|
for (int i = 0; i < 4; i++) {
|
|
int radio_rssi_threshold = -60 - i * 10;
|
|
int wifi_rssi_threshold = -60 - i * 10;
|
|
if (mDisplayData->RadioRSSI > radio_rssi_threshold)
|
|
mDisplay->drawBox(xoffs + mPixelshift, 8 + (rssi_bar_height + 1) * i, 4 - i, rssi_bar_height);
|
|
if (mDisplayData->WifiRSSI > wifi_rssi_threshold)
|
|
mDisplay->drawBox(mDispWidth - 4 - xoffs + mPixelshift + i, 8 + (rssi_bar_height + 1) * i, 4 - i, rssi_bar_height);
|
|
}
|
|
// draw dynamic antenna and WiFi symbols
|
|
mDisplay->setFont(u8g2_font_ncenB10_symbols10_ahoy);
|
|
char sym[]=" ";
|
|
sym[0] = mDisplayData->RadioSymbol?'A':'E'; // NRF
|
|
mDisplay->drawStr(xoffs + mPixelshift, mLineYOffsets[l_RSSI], sym);
|
|
|
|
if (mDisplayData->MQTTSymbol)
|
|
sym[0] = 'J'; // MQTT
|
|
else
|
|
sym[0] = mDisplayData->WifiSymbol?'B':'F'; // Wifi
|
|
mDisplay->drawStr(mDispWidth - mDisplay->getStrWidth(sym) - xoffs + mPixelshift, mLineYOffsets[l_RSSI], sym);
|
|
mDisplay->sendBuffer();
|
|
|
|
|
|
mDisplay->sendBuffer();
|
|
|
|
mExtra++;
|
|
}
|
|
|
|
private:
|
|
enum _dispLine {
|
|
// start page
|
|
l_Website = 0,
|
|
l_Ahoy = 2,
|
|
l_Version = 4,
|
|
// run page
|
|
l_Time = 0,
|
|
l_Status = 1,
|
|
l_TotalPower = 2,
|
|
l_YieldDay = 3,
|
|
l_YieldTotal = 4,
|
|
// run page - rssi bar symbols
|
|
l_RSSI = 4,
|
|
// End
|
|
l_MAX_LINES = 5,
|
|
};
|
|
|
|
const uint8_t pixelShiftRange = 11; // number of pixels to shift from left to right (centered -> must be odd!)
|
|
|
|
void calcLinePositions() {
|
|
uint8_t yOff = 0;
|
|
uint8_t i = 0;
|
|
uint8_t asc, dsc;
|
|
|
|
do {
|
|
setLineFont(i);
|
|
asc = mDisplay->getAscent();
|
|
yOff += asc;
|
|
mLineYOffsets[i] = yOff;
|
|
dsc = mDisplay->getDescent();
|
|
yOff -= dsc;
|
|
if (l_Time==i) // prevent time and status line to touch
|
|
yOff+=1; // -> one pixels space
|
|
i++;
|
|
} while(l_MAX_LINES>i);
|
|
}
|
|
|
|
inline void setLineFont(uint8_t line) {
|
|
if ((line == l_TotalPower) ||
|
|
(line == l_Ahoy))
|
|
mDisplay->setFont(u8g2_font_ncenB14_tr);
|
|
else if ((line == l_YieldDay) ||
|
|
(line == l_YieldTotal))
|
|
// mDisplay->setFont(u8g2_font_5x8_symbols_ahoy);
|
|
mDisplay->setFont(u8g2_font_ncenB10_tr);
|
|
else
|
|
mDisplay->setFont(u8g2_font_ncenB08_tr);
|
|
}
|
|
|
|
void printText(const char *text, uint8_t line, uint8_t col=0) {
|
|
uint8_t dispX;
|
|
setLineFont(line);
|
|
if (0xff == col)
|
|
dispX = (mDispWidth - mDisplay->getStrWidth(text)) / 2; // center text
|
|
else
|
|
dispX = col;
|
|
dispX += mPixelshift;
|
|
mDisplay->drawStr(dispX, mLineYOffsets[line], text);
|
|
}
|
|
};
|
|
|