From bb1eee6cda3339a63f44631c9137d15a1d29c0d3 Mon Sep 17 00:00:00 2001 From: Moirtz Wagner Date: Fri, 7 Nov 2025 23:10:15 +0100 Subject: [PATCH] Add outdoor temperature ant time display. --- Raumtermostat/platformio.ini | 6 +++--- Raumtermostat/src/MQTT.cpp | 6 ++++++ Raumtermostat/src/MQTT.h | 1 + Raumtermostat/src/main.cpp | 6 +++++- Raumtermostat/src/ui/Bootstrap_Icons_18.c | 3 ++- Raumtermostat/src/ui/actions.cpp | 18 ++++++++++++++++++ Raumtermostat/src/ui/actions.h | 1 + Raumtermostat/src/ui/screens.c | 20 ++++++++++++++++++++ Raumtermostat/src/ui/screens.h | 2 ++ Raumtermostat/src/ui/vars.cpp | 2 +- Raumtermostat/src/ui/vars.h | 1 + 11 files changed, 60 insertions(+), 6 deletions(-) diff --git a/Raumtermostat/platformio.ini b/Raumtermostat/platformio.ini index 97ef617..7c1e15a 100644 --- a/Raumtermostat/platformio.ini +++ b/Raumtermostat/platformio.ini @@ -14,8 +14,8 @@ board = seeed_xiao_esp32c3 monitor_speed = 115200 framework = arduino board_build.partitions = min_spiffs.csv -;upload_protocol = espota -;upload_port = TMP-EG-Bad.fritz.box +upload_protocol = espota +upload_port = TMP-EG-WoZi.fritz.box lib_deps = moononournation/GFX Library for Arduino@^1.5.3 lvgl/lvgl@^9.2.2 @@ -26,4 +26,4 @@ build_flags = -D LV_LVGL_H_INCLUDE_SIMPLE -I src ;to install on all targets: - ;(pio run -t nobuild -t upload --upload-port TMP-EG-WoZi.fritz.box) -and (pio run -t nobuild -t upload --upload-port TMP-EG-Florian.fritz.box) -and (pio run -t nobuild -t upload --upload-port TMP-EG-Bad.fritz.box) \ No newline at end of file + ;(pio run -t nobuild -t upload --upload-port TMP-EG-WoZi.fritz.box) -and (pio run -t nobuild -t upload --upload-port TMP-EG-Florian.fritz.box) -and (pio run -t nobuild -t upload --upload-port TMP-EG-Bad.fritz.box) -and (pio run -t nobuild -t upload --upload-port TMP-OG-Bad.fritz.box) -and (pio run -t nobuild -t upload --upload-port TMP-OG-Buero.fritz.box) -and (pio run -t nobuild -t upload --upload-port TMP-OG-KiZi.fritz.box) -and (pio run -t nobuild -t upload --upload-port TMP-OGSchlafen.fritz.box) -and (pio run -t nobuild -t upload --upload-port TMP-OGWoZi.fritz.box) -and (pio run -t nobuild -t upload --upload-port TMP-UG-Bad.fritz.box) -and (pio run -t nobuild -t upload --upload-port TMP-UG-Buero.fritz.box) -and (pio run -t nobuild -t upload --upload-port TMP-UG-Kueche.fritz.box) \ No newline at end of file diff --git a/Raumtermostat/src/MQTT.cpp b/Raumtermostat/src/MQTT.cpp index 3fdce50..0c4a39d 100644 --- a/Raumtermostat/src/MQTT.cpp +++ b/Raumtermostat/src/MQTT.cpp @@ -47,6 +47,7 @@ void MQTT::begin(){ wm.addParameter(&custom_ntpServer); psclient.setClient(client); psclient.setServer(Settings::prefs.mqtt_server,Settings::prefs.mqtt_port); + psclient.setCallback(receiveTopic); WiFi.setHostname(custom_hostname.getValue()); //define hostname wm.setConfigPortalBlocking(false); if(wm.autoConnect("TempReglerAP")){ @@ -127,11 +128,16 @@ void MQTT::saveConfigToFlash(void){ Settings::getInstance().saveSettings(); // Save dataset to persistent storage } +void MQTT::receiveTopic(char* topic, byte* payload, unsigned int length) { + glblData.outTemp = String((char*)payload).toFloat(); + } + void MQTT::reconnect(void) { // Loop until we're reconnected Serial.print("Attempting MQTT connection..."); // Attempt to connect if (psclient.connect(Settings::prefs.hostname)) { + psclient.subscribe("weatherStation/tempAmb"); Serial.println("connected"); } else { diff --git a/Raumtermostat/src/MQTT.h b/Raumtermostat/src/MQTT.h index 98848db..23c648c 100644 --- a/Raumtermostat/src/MQTT.h +++ b/Raumtermostat/src/MQTT.h @@ -40,6 +40,7 @@ public: char* getHostname(void); char* getMqttTopic(void); char* getMyIP(void); + static void receiveTopic(char* topic, byte* payload, unsigned int length); void begin(); void loop(void); void publish(const char* msg); diff --git a/Raumtermostat/src/main.cpp b/Raumtermostat/src/main.cpp index ae0584c..4bf0075 100644 --- a/Raumtermostat/src/main.cpp +++ b/Raumtermostat/src/main.cpp @@ -153,12 +153,16 @@ void loop() chart_autoscale(); lv_chart_refresh(objects.chart); } - if(millis() - minutesTick > 10000){ + if(millis() - minutesTick > 60000){ minutesTick = millis(); if(mqtt.wifiConnected){ update_wifi_strength(glblData.wifiStrength,glblData.wifiMode); } } + if(millis() - secondsTick > 1000){ + secondsTick = millis(); + update_clockdots(); + } mqtt.loop(); ui_tick(); if(!ui_isSleeping()){ diff --git a/Raumtermostat/src/ui/Bootstrap_Icons_18.c b/Raumtermostat/src/ui/Bootstrap_Icons_18.c index bf76ce2..be4394f 100644 --- a/Raumtermostat/src/ui/Bootstrap_Icons_18.c +++ b/Raumtermostat/src/ui/Bootstrap_Icons_18.c @@ -465,7 +465,8 @@ lv_font_t Bootstrap_Icons_18 = { #endif .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ #if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, + + .fallback = &lv_font_montserrat_20, #endif .user_data = NULL, }; diff --git a/Raumtermostat/src/ui/actions.cpp b/Raumtermostat/src/ui/actions.cpp index 92671ce..570b6a1 100644 --- a/Raumtermostat/src/ui/actions.cpp +++ b/Raumtermostat/src/ui/actions.cpp @@ -16,6 +16,18 @@ void update_sensorNstatus(float temp, float hum, float seaLevelPress, bool presA glblData.presAlarm = presAlarm; update_status(); } +void update_clockdots(void){ + static bool dotState = false; + dotState = !dotState; + char* time = lv_label_get_text(objects.time_txt); + if(dotState){ + time[3] = ':'; + lv_label_set_text(objects.time_txt, time); + }else{ + time[3] = ' '; + lv_label_set_text(objects.time_txt, time); + } +} static void alarm_ani_cb(void * var, int32_t v) { @@ -38,9 +50,15 @@ void ui_settemp(float tmp){ } void update_status(void){ + tm timeinfo; + getLocalTime(&timeinfo); + char buffer[15]; + strftime(buffer, sizeof(buffer), "%R", &timeinfo); static unsigned long fullOnTime = millis(); lv_label_set_text_fmt(objects.press_txt,"%4.2f hPa",glblData.seaLevelPress); lv_label_set_text_fmt(objects.hum_txt,"%2.0f %%rH",glblData.hum); + lv_label_set_text_fmt(objects.outTemp_txt,ICON_THERMOMETER_SNOW "%2.1f °C",glblData.outTemp); + lv_label_set_text(objects.time_txt,buffer); if(!arc_pressed && !animating){ lv_label_set_text_fmt(objects.temp_txt,"%2.1f °C",glblData.temp); }else{ diff --git a/Raumtermostat/src/ui/actions.h b/Raumtermostat/src/ui/actions.h index f92d04b..703059d 100644 --- a/Raumtermostat/src/ui/actions.h +++ b/Raumtermostat/src/ui/actions.h @@ -20,6 +20,7 @@ void rebootESP(lv_event_t * e); void action_show_cursors_cb(lv_event_t * e); void chartDrawingCB(lv_event_t * e); void update_sensorNstatus(float temp, float hum, float seaLevelPress, bool presAlarm); +void update_clockdots(void); void update_status(void); void update_wifi_strength(wifistrength_t strength, wifimode_t mode); void chart_autoscale(void); diff --git a/Raumtermostat/src/ui/screens.c b/Raumtermostat/src/ui/screens.c index 5f492d6..16162b0 100644 --- a/Raumtermostat/src/ui/screens.c +++ b/Raumtermostat/src/ui/screens.c @@ -76,6 +76,7 @@ void create_screen_main() { lv_label_set_text(obj, ""); lv_obj_set_style_text_font(obj, &lv_font_montserrat_20, LV_PART_MAIN | LV_STATE_DEFAULT); } + { // pressTxt lv_obj_t *obj = lv_label_create(parent_obj); @@ -86,6 +87,25 @@ void create_screen_main() { lv_label_set_text(obj, ""); lv_obj_set_style_text_font(obj, &lv_font_montserrat_20, LV_PART_MAIN | LV_STATE_DEFAULT); } + { + // timeTxt + lv_obj_t *obj = lv_label_create(parent_obj); + objects.time_txt = obj; + lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); + lv_obj_align(obj,LV_ALIGN_CENTER,0,-60); + lv_label_set_text(obj, ""); + lv_obj_set_style_text_font(obj, &Bootstrap_Icons_18, LV_PART_MAIN | LV_STATE_DEFAULT); + } + + { + // outTemp + lv_obj_t *obj = lv_label_create(parent_obj); + objects.outTemp_txt = obj; + lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); + lv_obj_align(obj,LV_ALIGN_CENTER,0,55); + lv_label_set_text(obj, ICON_THERMOMETER_SNOW "--°C"); + lv_obj_set_style_text_font(obj, &Bootstrap_Icons_18, LV_PART_MAIN | LV_STATE_DEFAULT); + } { // Heating active lv_obj_t *obj = lv_label_create(parent_obj); diff --git a/Raumtermostat/src/ui/screens.h b/Raumtermostat/src/ui/screens.h index 7b83bba..72654cd 100644 --- a/Raumtermostat/src/ui/screens.h +++ b/Raumtermostat/src/ui/screens.h @@ -27,6 +27,8 @@ typedef struct _objects_t { lv_obj_t *bufferIcn; lv_obj_t *wifiIcn; lv_obj_t *alarmLED; + lv_obj_t *outTemp_txt; + lv_obj_t *time_txt; lv_chart_cursor_t *chart_cursor; lv_chart_series_t *chart_series; } objects_t; diff --git a/Raumtermostat/src/ui/vars.cpp b/Raumtermostat/src/ui/vars.cpp index 56a289f..d9b2f2f 100644 --- a/Raumtermostat/src/ui/vars.cpp +++ b/Raumtermostat/src/ui/vars.cpp @@ -4,7 +4,7 @@ bool history_initialized = false; -dataset_t glblData = {.temp = NAN, .hum = NAN, .pres = NAN, .seaLevelPress = NAN, .settemp= NAN, .heating=false, .enBuff =false, .relPowerSave=true, .presAlarm=false, .myIP={0}, .wifiStrength = WIFISTRENGTH_OFF, .wifiMode= WIFIMODE_OFF, .override = OVR_NONE, .bootTime = {0}}; +dataset_t glblData = {.temp = NAN, .hum = NAN, .pres = NAN, .seaLevelPress = NAN, .settemp= NAN, .outTemp = NAN, .heating=false, .enBuff =false, .relPowerSave=true, .presAlarm=false, .myIP={0}, .wifiStrength = WIFISTRENGTH_OFF, .wifiMode= WIFIMODE_OFF, .override = OVR_NONE, .bootTime = {0}}; hist_t history = {{0},{0},{0}}; int32_t* history_getPressPt(void){ diff --git a/Raumtermostat/src/ui/vars.h b/Raumtermostat/src/ui/vars.h index 864bc79..9cfe9b3 100644 --- a/Raumtermostat/src/ui/vars.h +++ b/Raumtermostat/src/ui/vars.h @@ -52,6 +52,7 @@ typedef struct dataset_s{ float pres; float seaLevelPress; float settemp; + float outTemp; bool heating; bool enBuff; bool relPowerSave;