Feature: Added localization setting to display

Its possible to change the language of the display
This commit is contained in:
Thomas Basler 2023-05-23 18:25:12 +02:00
parent 4e11d653a3
commit 752362d2df
12 changed files with 72 additions and 7 deletions

View File

@ -109,6 +109,7 @@ struct CONFIG_T {
bool Display_ScreenSaver; bool Display_ScreenSaver;
uint8_t Display_Rotation; uint8_t Display_Rotation;
uint8_t Display_Contrast; uint8_t Display_Contrast;
uint8_t Display_Language;
}; };
class ConfigurationClass { class ConfigurationClass {

View File

@ -20,6 +20,7 @@ public:
void loop(); void loop();
void setContrast(uint8_t contrast); void setContrast(uint8_t contrast);
void setOrientation(uint8_t rotation = DISPLAY_ROTATION); void setOrientation(uint8_t rotation = DISPLAY_ROTATION);
void setLanguage(uint8_t language);
void setStartupDisplay(); void setStartupDisplay();
bool enablePowerSafe = true; bool enablePowerSafe = true;
@ -33,6 +34,7 @@ private:
U8G2* _display; U8G2* _display;
DisplayType_t _display_type = DisplayType_t::None; DisplayType_t _display_type = DisplayType_t::None;
uint8_t _display_language = DISPLAY_LANGUAGE;
uint8_t _mExtra; uint8_t _mExtra;
uint16_t _period = 1000; uint16_t _period = 1000;
uint16_t _interval = 60000; // interval at which to power save (milliseconds) uint16_t _interval = 60000; // interval at which to power save (milliseconds)

View File

@ -92,3 +92,4 @@
#define DISPLAY_SCREENSAVER true #define DISPLAY_SCREENSAVER true
#define DISPLAY_ROTATION 2 #define DISPLAY_ROTATION 2
#define DISPLAY_CONTRAST 60 #define DISPLAY_CONTRAST 60
#define DISPLAY_LANGUAGE 0

View File

@ -95,6 +95,7 @@ bool ConfigurationClass::write()
display["screensaver"] = config.Display_ScreenSaver; display["screensaver"] = config.Display_ScreenSaver;
display["rotation"] = config.Display_Rotation; display["rotation"] = config.Display_Rotation;
display["contrast"] = config.Display_Contrast; display["contrast"] = config.Display_Contrast;
display["language"] = config.Display_Language;
JsonArray inverters = doc.createNestedArray("inverters"); JsonArray inverters = doc.createNestedArray("inverters");
for (uint8_t i = 0; i < INV_MAX_COUNT; i++) { for (uint8_t i = 0; i < INV_MAX_COUNT; i++) {
@ -237,6 +238,7 @@ bool ConfigurationClass::read()
config.Display_ScreenSaver = display["screensaver"] | DISPLAY_SCREENSAVER; config.Display_ScreenSaver = display["screensaver"] | DISPLAY_SCREENSAVER;
config.Display_Rotation = display["rotation"] | DISPLAY_ROTATION; config.Display_Rotation = display["rotation"] | DISPLAY_ROTATION;
config.Display_Contrast = display["contrast"] | DISPLAY_CONTRAST; config.Display_Contrast = display["contrast"] | DISPLAY_CONTRAST;
config.Display_Language = display["language"] | DISPLAY_LANGUAGE;
JsonArray inverters = doc["inverters"]; JsonArray inverters = doc["inverters"];
for (uint8_t i = 0; i < INV_MAX_COUNT; i++) { for (uint8_t i = 0; i < INV_MAX_COUNT; i++) {

View File

@ -11,6 +11,25 @@ std::map<DisplayType_t, std::function<U8G2*(uint8_t, uint8_t, uint8_t, uint8_t)>
{ DisplayType_t::SH1106, [](uint8_t reset, uint8_t clock, uint8_t data, uint8_t cs) { return new U8G2_SH1106_128X64_NONAME_F_HW_I2C(U8G2_R0, reset, clock, data); } }, { DisplayType_t::SH1106, [](uint8_t reset, uint8_t clock, uint8_t data, uint8_t cs) { return new U8G2_SH1106_128X64_NONAME_F_HW_I2C(U8G2_R0, reset, clock, data); } },
}; };
// Language defintion, respect order in languages[] and translation lists
#define I18N_LOCALE_EN 0
#define I18N_LOCALE_DE 1
#define I18N_LOCALE_FR 2
// Languages supported. Note: the order is important and must match locale_translations.h
const uint8_t languages[] = {
I18N_LOCALE_EN,
I18N_LOCALE_DE,
I18N_LOCALE_FR
};
static const char* const i18n_offline[] = { "Offline", "Offline", "Offline" };
static const char* const i18n_current_power_w[] = { "%3.0f W", "%3.0f W", "%3.0f W" };
static const char* const i18n_current_power_kw[] = { "%2.1f kW", "%2.1f kW", "%2.1f kW" };
static const char* const i18n_yield_today_wh[] = { "today: %4.0f Wh", "Heute: %4.0f Wh", "auj.: %4.0f Wh" };
static const char* const i18n_yield_total_kwh[] = { "total: %.1f kWh", "Ges.: %.1f kWh", "total: %.1f kWh" };
static const char* const i18n_date_format[] = { "%m/%d/%Y %H:%M", "%d.%m.%Y %H:%M", "%d/%m/%Y %H:%M" };
DisplayGraphicClass::DisplayGraphicClass() DisplayGraphicClass::DisplayGraphicClass()
{ {
} }
@ -95,6 +114,11 @@ void DisplayGraphicClass::setOrientation(uint8_t rotation)
calcLineHeights(); calcLineHeights();
} }
void DisplayGraphicClass::setLanguage(uint8_t language)
{
_display_language = language < sizeof(languages) / sizeof(languages[0]) ? language : DISPLAY_LANGUAGE;
}
void DisplayGraphicClass::setStartupDisplay() void DisplayGraphicClass::setStartupDisplay()
{ {
if (_display_type == DisplayType_t::None) { if (_display_type == DisplayType_t::None) {
@ -120,9 +144,9 @@ void DisplayGraphicClass::loop()
if (Datastore.isAtLeastOneReachable) { if (Datastore.isAtLeastOneReachable) {
_display->setPowerSave(false); _display->setPowerSave(false);
if (Datastore.totalAcPowerEnabled > 999) { if (Datastore.totalAcPowerEnabled > 999) {
snprintf(_fmtText, sizeof(_fmtText), "%2.1f kW", (Datastore.totalAcPowerEnabled / 1000)); snprintf(_fmtText, sizeof(_fmtText), i18n_current_power_kw[_display_language], (Datastore.totalAcPowerEnabled / 1000));
} else { } else {
snprintf(_fmtText, sizeof(_fmtText), "%3.0f W", Datastore.totalAcPowerEnabled); snprintf(_fmtText, sizeof(_fmtText), i18n_current_power_w[_display_language], Datastore.totalAcPowerEnabled);
} }
printText(_fmtText, 0); printText(_fmtText, 0);
_previousMillis = millis(); _previousMillis = millis();
@ -131,7 +155,7 @@ void DisplayGraphicClass::loop()
//=====> Offline =========== //=====> Offline ===========
else { else {
printText("offline", 0); printText(i18n_offline[_display_language], 0);
// check if it's time to enter power saving mode // check if it's time to enter power saving mode
if (millis() - _previousMillis >= (_interval * 2)) { if (millis() - _previousMillis >= (_interval * 2)) {
_display->setPowerSave(enablePowerSafe); _display->setPowerSave(enablePowerSafe);
@ -140,10 +164,10 @@ void DisplayGraphicClass::loop()
//<======================= //<=======================
//=====> Today & Total Production ======= //=====> Today & Total Production =======
snprintf(_fmtText, sizeof(_fmtText), "today: %4.0f Wh", Datastore.totalAcYieldDayEnabled); snprintf(_fmtText, sizeof(_fmtText), i18n_yield_today_wh[_display_language], Datastore.totalAcYieldDayEnabled);
printText(_fmtText, 1); printText(_fmtText, 1);
snprintf(_fmtText, sizeof(_fmtText), "total: %.1f kWh", Datastore.totalAcYieldTotalEnabled); snprintf(_fmtText, sizeof(_fmtText), i18n_yield_total_kwh[_display_language], Datastore.totalAcYieldTotalEnabled);
printText(_fmtText, 2); printText(_fmtText, 2);
//<======================= //<=======================
@ -153,7 +177,7 @@ void DisplayGraphicClass::loop()
} else { } else {
// Get current time // Get current time
time_t now = time(nullptr); time_t now = time(nullptr);
strftime(_fmtText, sizeof(_fmtText), "%a %d.%m.%Y %H:%M", localtime(&now)); strftime(_fmtText, sizeof(_fmtText), i18n_date_format[_display_language], localtime(&now));
printText(_fmtText, 3); printText(_fmtText, 3);
} }
_display->sendBuffer(); _display->sendBuffer();

View File

@ -80,6 +80,7 @@ void WebApiDeviceClass::onDeviceAdminGet(AsyncWebServerRequest* request)
display["power_safe"] = config.Display_PowerSafe; display["power_safe"] = config.Display_PowerSafe;
display["screensaver"] = config.Display_ScreenSaver; display["screensaver"] = config.Display_ScreenSaver;
display["contrast"] = config.Display_Contrast; display["contrast"] = config.Display_Contrast;
display["language"] = config.Display_Language;
response->setLength(); response->setLength();
request->send(response); request->send(response);
@ -149,11 +150,13 @@ void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request)
config.Display_PowerSafe = root["display"]["power_safe"].as<bool>(); config.Display_PowerSafe = root["display"]["power_safe"].as<bool>();
config.Display_ScreenSaver = root["display"]["screensaver"].as<bool>(); config.Display_ScreenSaver = root["display"]["screensaver"].as<bool>();
config.Display_Contrast = root["display"]["contrast"].as<uint8_t>(); config.Display_Contrast = root["display"]["contrast"].as<uint8_t>();
config.Display_Language = root["display"]["language"].as<uint8_t>();
Display.setOrientation(config.Display_Rotation); Display.setOrientation(config.Display_Rotation);
Display.enablePowerSafe = config.Display_PowerSafe; Display.enablePowerSafe = config.Display_PowerSafe;
Display.enableScreensaver = config.Display_ScreenSaver; Display.enableScreensaver = config.Display_ScreenSaver;
Display.setContrast(config.Display_Contrast); Display.setContrast(config.Display_Contrast);
Display.setLanguage(config.Display_Language);
Configuration.write(); Configuration.write();

View File

@ -120,6 +120,7 @@ void setup()
Display.enablePowerSafe = config.Display_PowerSafe; Display.enablePowerSafe = config.Display_PowerSafe;
Display.enableScreensaver = config.Display_ScreenSaver; Display.enableScreensaver = config.Display_ScreenSaver;
Display.setContrast(config.Display_Contrast); Display.setContrast(config.Display_Contrast);
Display.setLanguage(config.Display_Language);
Display.setStartupDisplay(); Display.setStartupDisplay();
MessageOutput.println("done"); MessageOutput.println("done");

View File

@ -530,6 +530,10 @@
"Rotation": "Rotation:", "Rotation": "Rotation:",
"rot0": "Keine Rotation", "rot0": "Keine Rotation",
"rot90": "90 Grad Drehung", "rot90": "90 Grad Drehung",
"DisplayLanguage": "Displaysprache:",
"en": "Englisch",
"de": "Deutsch",
"fr": "Französisch",
"rot180": "180 Grad Drehung", "rot180": "180 Grad Drehung",
"rot270": "270 Grad Drehung", "rot270": "270 Grad Drehung",
"Save": "@:dtuadmin.Save" "Save": "@:dtuadmin.Save"

View File

@ -532,6 +532,10 @@
"rot90": "90 degree rotation", "rot90": "90 degree rotation",
"rot180": "180 degree rotation", "rot180": "180 degree rotation",
"rot270": "270 degree rotation", "rot270": "270 degree rotation",
"DisplayLanguage": "Display language:",
"en": "English",
"de": "German",
"fr": "French",
"Save": "@:dtuadmin.Save" "Save": "@:dtuadmin.Save"
}, },
"pininfo": { "pininfo": {

View File

@ -532,6 +532,10 @@
"rot90": "90 degree rotation", "rot90": "90 degree rotation",
"rot180": "180 degree rotation", "rot180": "180 degree rotation",
"rot270": "270 degree rotation", "rot270": "270 degree rotation",
"DisplayLanguage": "Langue d'affichage",
"en": "Anglais",
"de": "Allemand",
"fr": "Français",
"Save": "@:dtuadmin.Save" "Save": "@:dtuadmin.Save"
}, },
"pininfo": { "pininfo": {

View File

@ -5,6 +5,7 @@ export interface Display {
power_safe: boolean; power_safe: boolean;
screensaver: boolean; screensaver: boolean;
contrast: number; contrast: number;
language: number;
} }
export interface DeviceConfig { export interface DeviceConfig {

View File

@ -56,6 +56,19 @@
v-model="deviceConfigList.display.screensaver" type="checkbox" v-model="deviceConfigList.display.screensaver" type="checkbox"
:tooltip="$t('deviceadmin.ScreensaverHint')" /> :tooltip="$t('deviceadmin.ScreensaverHint')" />
<div class="row mb-3">
<label class="col-sm-2 col-form-label">
{{ $t('deviceadmin.DisplayLanguage') }}
</label>
<div class="col-sm-10">
<select class="form-select" v-model="deviceConfigList.display.language">
<option v-for="language in displayLanguageList" :key="language.key" :value="language.key">
{{ $t(`deviceadmin.` + language.value) }}
</option>
</select>
</div>
</div>
<div class="row mb-3"> <div class="row mb-3">
<label class="col-sm-2 col-form-label"> <label class="col-sm-2 col-form-label">
{{ $t('deviceadmin.Rotation') }} {{ $t('deviceadmin.Rotation') }}
@ -123,6 +136,11 @@ export default defineComponent({
{ key: 2, value: 'rot180' }, { key: 2, value: 'rot180' },
{ key: 3, value: 'rot270' }, { key: 3, value: 'rot270' },
], ],
displayLanguageList: [
{ key: 0, value: "en" },
{ key: 1, value: "de" },
{ key: 2, value: "fr" },
],
} }
}, },
created() { created() {