From 346abc2415095b4b8681cf9123ea01f6686bbcbc Mon Sep 17 00:00:00 2001 From: rxf Date: Sat, 6 Jul 2024 00:39:35 +0200 Subject: [PATCH] First commit - WIP --- .gitignore | 7 +++ .vscode/extensions.json | 10 +++ platformio.ini | 23 +++++++ src/grafik.cpp | 135 ++++++++++++++++++++++++++++++++++++++++ src/grafik.h | 52 ++++++++++++++++ src/handlebme280.cpp | 41 ++++++++++++ src/handlebme280.h | 21 +++++++ src/main.cpp | 89 ++++++++++++++++++++++++++ src/main.h | 16 +++++ src/mqtt.cpp | 61 ++++++++++++++++++ src/mqtt.h | 31 +++++++++ src/weifi.cpp | 28 +++++++++ src/weifi.h | 19 ++++++ 13 files changed, 533 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/extensions.json create mode 100644 platformio.ini create mode 100644 src/grafik.cpp create mode 100644 src/grafik.h create mode 100644 src/handlebme280.cpp create mode 100644 src/handlebme280.h create mode 100644 src/main.cpp create mode 100644 src/main.h create mode 100644 src/mqtt.cpp create mode 100644 src/mqtt.h create mode 100644 src/weifi.cpp create mode 100644 src/weifi.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5863e89 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch +.DS_STORE +README \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..080e70d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" + ] +} diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..70ea1d5 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,23 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp32dev] +platform = espressif32 +board = esp32dev +framework = arduino +lib_deps = + https://github.com/me-no-dev/AsyncTCP/archive/refs/heads/master.zip + https://github.com/marvinroger/async-mqtt-client/archive/refs/heads/develop.zip + bblanchon/ArduinoJson@^7.1.0 + adafruit/Adafruit BME280 Library@^2.2.4 + lvgl/lvgl@^9.1.0 + bodmer/TFT_eSPI@^2.5.43 + +monitor_speed = 115200 diff --git a/src/grafik.cpp b/src/grafik.cpp new file mode 100644 index 0000000..bd9f0f9 --- /dev/null +++ b/src/grafik.cpp @@ -0,0 +1,135 @@ +// Grafik Routinen +#define GRAFIK + +#include "grafik.h" + +#define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 10 * (LV_COLOR_DEPTH / 8)) +uint32_t draw_buf[DRAW_BUF_SIZE / 4]; + +void setup_grafik(void) { + lv_init(); + lv_display_t * disp; + disp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf)); +} + +void buildarc(ARC arc) { + lv_obj_set_size(arc.arc, arc.size, arc.size); + lv_arc_set_rotation(arc.arc, 180); + lv_arc_set_bg_angles(arc.arc, 0, 180); + lv_arc_set_value(arc.arc, arc.value); + lv_obj_align(arc.arc, LV_ALIGN_LEFT_MID, arc.x, arc.y); + lv_obj_remove_style(arc.arc, NULL, LV_PART_KNOB); + + // Style this arc + static lv_style_t style_arc; + lv_style_init(&style_arc); + lv_style_set_arc_width(&style_arc, 20); + lv_style_set_arc_rounded(&style_arc, false); + lv_obj_add_style(arc.arc, &style_arc, LV_PART_MAIN); + lv_obj_add_style(arc.arc, &style_arc, LV_PART_INDICATOR); + + lv_obj_t * low_label = lv_label_create(arc.arc); + char valuelow[10]; + sprintf(valuelow, "%d", arc.lowvalue); + lv_label_set_text(low_label, valuelow); + lv_obj_align(low_label, LV_ALIGN_LEFT_MID, 0, 8); + static lv_style_t style_low_label; + lv_style_init(&style_low_label); + lv_style_set_text_font(&style_low_label, &lv_font_montserrat_10); + lv_obj_add_style(low_label, &style_low_label, 0); + + lv_obj_t * value_label = lv_label_create(arc.arc); + char value[10]; + sprintf(value, arc.valformat, arc.value); + Serial.println(value); + lv_label_set_text(value_label, value); + lv_obj_align(value_label, LV_ALIGN_LEFT_MID, 38, -10); + static lv_style_t style_value_label; + lv_style_init(&style_value_label); + lv_style_set_text_font(&style_value_label, &lv_font_montserrat_18); + lv_obj_add_style(value_label, &style_value_label, 0); + + lv_obj_t * high_label = lv_label_create(arc.arc); + char valuehigh[10]; + sprintf(valuehigh, "%d", arc.highvalue); + lv_label_set_text(high_label, valuehigh); + lv_obj_align(high_label, LV_ALIGN_LEFT_MID, 90, 8); + static lv_style_t style_high_label; + lv_style_init(&style_high_label); + lv_style_set_text_font(&style_high_label, &lv_font_montserrat_10); + lv_obj_add_style(high_label, &style_high_label, 0); + + lv_obj_t * unit_label = lv_label_create(arc.arc); + lv_label_set_text(unit_label, arc.unit); + lv_obj_align(unit_label, LV_ALIGN_LEFT_MID, 48, 8); + static lv_style_t style_unit_label; + lv_style_init(&style_unit_label); + lv_style_set_text_font(&style_unit_label, &lv_font_montserrat_12); + lv_obj_add_style(unit_label, &style_unit_label, 0); +} + +void lv_create_main_gui(void) { + // Create a text label aligned on top: https://docs.lvgl.io/master/widgets/label.html + lv_obj_t * date_label = lv_label_create(lv_screen_active()); + lv_label_set_text(date_label, "17:30"); + lv_obj_align(date_label, LV_ALIGN_TOP_MID, 0, 10); + + // Set font type and font size. More information: https://docs.lvgl.io/master/overview/font.html + static lv_style_t style_date_label; + lv_style_init(&style_date_label); + lv_style_set_text_font(&style_date_label, &lv_font_montserrat_28); + lv_obj_add_style(date_label, &style_date_label, 0); + + // Create a text label aligned on top: https://docs.lvgl.io/master/widgets/label.html + lv_obj_t * time_label = lv_label_create(lv_screen_active()); + lv_label_set_text(time_label, "Dienstag, 12. Dezember 2024"); + lv_obj_align(time_label, LV_ALIGN_TOP_MID, 0, 40); + + // Set font type and font size. More information: https://docs.lvgl.io/master/overview/font.html + static lv_style_t style_time_label; + lv_style_init(&style_time_label); + lv_style_set_text_font(&style_time_label, &lv_font_montserrat_12); + lv_obj_add_style(time_label, &style_time_label, 0); + + // lv_obj_t * label = lv_label_create(lv_screen_active()); + + /*Create an Arc*/ + lv_obj_t * aTemp = lv_arc_create(lv_screen_active()); + arcTemp.arc = aTemp; + buildarc(arcTemp); + lv_obj_t * aHum = lv_arc_create(lv_screen_active()); + arcHum.arc = aHum; + buildarc(arcHum); +} + +void setValuetoArc(ARC arc, float value) { + char s[60]; + int r = arc.highvalue - arc.lowvalue; + int v = (value - arc.lowvalue) * 100 / r; + arc.value = v; + sprintf(s,"high: %d, low: %d, value: %.1f, v: %d\n", arc.highvalue, arc.lowvalue, arc.value, v); + Serial.println(s); + lv_arc_set_value(arc.arc, arc.value); + lv_obj_t * value_label = lv_obj_get_child(arc.arc, 1); + char valuestr[10]; + sprintf(valuestr, arc.valformat, value); + lv_label_set_text(value_label, valuestr); + + sprintf(s,"name: %s, value: %.1f, green: %d, yellow: %d", arc.name, arc.value, arc.green, arc.yellow); + Serial.println(s); + static lv_style_t style_arc; + lv_style_init(&style_arc); + if (arc.value < arc.green) { + lv_style_set_arc_color(&style_arc, lv_palette_main(LV_PALETTE_GREEN)); + } else if (arc.value < arc.yellow) { + lv_style_set_arc_color(&style_arc, lv_palette_main(LV_PALETTE_YELLOW)); + } else { + lv_style_set_arc_color(&style_arc, lv_palette_main(LV_PALETTE_RED)); + } + lv_obj_add_style(arc.arc, &style_arc, LV_PART_INDICATOR); + + +} + + + diff --git a/src/grafik.h b/src/grafik.h new file mode 100644 index 0000000..8bcd476 --- /dev/null +++ b/src/grafik.h @@ -0,0 +1,52 @@ +#ifndef GRAFIK_H +#define GRAFIK_H + +/* Install the "lvgl" library version 9.X by kisvegabor to interface with the TFT Display - https://lvgl.io/ + *** IMPORTANT: lv_conf.h available on the internet will probably NOT work with the examples available at Random Nerd Tutorials *** + *** YOU MUST USE THE lv_conf.h FILE PROVIDED IN THE LINK BELOW IN ORDER TO USE THE EXAMPLES FROM RANDOM NERD TUTORIALS *** + FULL INSTRUCTIONS AVAILABLE ON HOW CONFIGURE THE LIBRARY: https://RandomNerdTutorials.com/cyd-lvgl/ or https://RandomNerdTutorials.com/esp32-tft-lvgl/ */ +#include + +/* Install the "TFT_eSPI" library by Bodmer to interface with the TFT Display - https://github.com/Bodmer/TFT_eSPI + *** IMPORTANT: User_Setup.h available on the internet will probably NOT work with the examples available at Random Nerd Tutorials *** + *** YOU MUST USE THE User_Setup.h FILE PROVIDED IN THE LINK BELOW IN ORDER TO USE THE EXAMPLES FROM RANDOM NERD TUTORIALS *** + FULL INSTRUCTIONS AVAILABLE ON HOW CONFIGURE THE LIBRARY: https://RandomNerdTutorials.com/cyd-lvgl/ or https://RandomNerdTutorials.com/esp32-tft-lvgl/ */ +#include + +typedef struct { + lv_obj_t * arc; + const char * name; + int x; + int y; + int size; + float value; + const char* valformat; + const char* const unit; + int lowvalue; + int highvalue; + int green; + int yellow; + +} ARC; + + + +#define SCREEN_WIDTH 320 +#define SCREEN_HEIGHT 240 + + +#ifdef MAIN +ARC arcTemp = {NULL, "temp", 30, 0, 110, 30.0, "%.1f", "°C", 10, 30, 20, 25}; +ARC arcHum = {NULL, "humi", 180, 0, 110, 60.0, "%.0f", "%",0, 100, 50, 70}; +#else +extern ARC arcTemp; +extern ARC arcHum; +#endif + + +void setup_grafik(void); +void lv_create_main_gui(void); +void setValuetoArc(ARC arc, float value); + + +#endif \ No newline at end of file diff --git a/src/handlebme280.cpp b/src/handlebme280.cpp new file mode 100644 index 0000000..090a04b --- /dev/null +++ b/src/handlebme280.cpp @@ -0,0 +1,41 @@ +// Routine für den BME280 + +#define BME280 + +#include "handlebme280.h" + +TwoWire I2CBME = TwoWire(0); +Adafruit_BME280 bme; + + +void initBME280() { + I2CBME.begin(I2C_SDA, I2C_SCL, 100000); + if (!bme.begin(0x76, &I2CBME)) { + Serial.println("Could not find a valid BME280 sensor, check wiring!"); + while (1); + } + Serial.println("BME280 sensor found!"); +} + +BME280Data readBME280() { + BME280Data data; + data.temp = bme.readTemperature(); + data.hum = bme.readHumidity(); + data.pres = bme.readPressure() / 100.0F; + + Serial.print("Temperature = "); + Serial.print(data.temp); + Serial.println(" °C"); + + Serial.print("Pressure = "); + Serial.print(data.pres); + Serial.println(" hPa"); + + Serial.print("Humidity = "); + Serial.print(data.hum); + Serial.println(" %"); + + Serial.println(); + +return data; +} \ No newline at end of file diff --git a/src/handlebme280.h b/src/handlebme280.h new file mode 100644 index 0000000..32ff1a3 --- /dev/null +++ b/src/handlebme280.h @@ -0,0 +1,21 @@ +#ifndef BME280H +#define BME280_H + +#include +#include +#include + +#define I2C_SDA 27 +#define I2C_SCL 22 + + +typedef struct { + float temp; + float hum; + float pres; +} BME280Data; + +void initBME280(); +BME280Data readBME280(); + +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..d1334a8 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,89 @@ +/* Rui Santos & Sara Santos - Random Nerd Tutorials - https://RandomNerdTutorials.com/esp32-lvgl-ebook/ + THIS EXAMPLE WAS TESTED WITH THE FOLLOWING HARDWARE: + 1) ESP32-2432S028R 2.8 inch 240×320 also known as the Cheap Yellow Display (CYD): https://makeradvisor.com/tools/cyd-cheap-yellow-display-esp32-2432s028r/ + SET UP INSTRUCTIONS: https://RandomNerdTutorials.com/cyd-lvgl/ + 2) REGULAR ESP32 Dev Board + 2.8 inch 240x320 TFT Display: https://makeradvisor.com/tools/2-8-inch-ili9341-tft-240x320/ and https://makeradvisor.com/tools/esp32-dev-board-wi-fi-bluetooth/ + SET UP INSTRUCTIONS: https://RandomNerdTutorials.com/esp32-tft-lvgl/ + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files. + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +*/ +#define MAIN + +/* Install the "lvgl" library version 9.X by kisvegabor to interface with the TFT Display - https://lvgl.io/ + *** IMPORTANT: lv_conf.h available on the internet will probably NOT work with the examples available at Random Nerd Tutorials *** + *** YOU MUST USE THE lv_conf.h FILE PROVIDED IN THE LINK BELOW IN ORDER TO USE THE EXAMPLES FROM RANDOM NERD TUTORIALS *** + FULL INSTRUCTIONS AVAILABLE ON HOW CONFIGURE THE LIBRARY: https://RandomNerdTutorials.com/cyd-lvgl/ or https://RandomNerdTutorials.com/esp32-tft-lvgl/ */ +#include + +/* Install the "TFT_eSPI" library by Bodmer to interface with the TFT Display - https://github.com/Bodmer/TFT_eSPI + *** IMPORTANT: User_Setup.h available on the internet will probably NOT work with the examples available at Random Nerd Tutorials *** + *** YOU MUST USE THE User_Setup.h FILE PROVIDED IN THE LINK BELOW IN ORDER TO USE THE EXAMPLES FROM RANDOM NERD TUTORIALS *** + FULL INSTRUCTIONS AVAILABLE ON HOW CONFIGURE THE LIBRARY: https://RandomNerdTutorials.com/cyd-lvgl/ or https://RandomNerdTutorials.com/esp32-tft-lvgl/ */ +#include + + +#include "Weifi.h" +#include "mqtt.h" +#include "handlebme280.h" +#include "grafik.h" +#include "main.h" + + +void setup() { +// String LVGL_Arduino = String("LVGL Library Version: ") + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch(); + delay (1000); + String LVGL_Arduino = String("LVGL Library Version: ") + "9.0.0"; + Serial.begin(115200); + Serial.println(LVGL_Arduino); + + initBME280(); + + // Start LVGL + setup_grafik(); + Serial.println("LVGL started"); + + // Function to draw the GUI + lv_create_main_gui(); + Serial.println("Main GUI created"); + +setValuetoArc(arcTemp, 25.3); +setValuetoArc(arcHum, 45.0); + delay(1000); + // Start WiFi + connectToWifi(); + Serial.println("WiFi started"); + + // Start MQTT + connectToMqtt(); + Serial.println("MQTT started"); +/* + // Register print function for debugging + lv_log_register_print_cb(log_print); + Serial.println("Print function registered"); + + // Function to draw the GUI + lv_create_main_gui(); + Serial.println("Main GUI created"); + + delay(1000); + + mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast(connectToMqtt)); + wifiReconnectTimer = xTimerCreate("wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast(connectToWifi)); + WiFi.onEvent(WiFiEvent); + mqttClient.onConnect(onMqttConnect); + mqttClient.onDisconnect(onMqttDisconnect); + mqttClient.onSubscribe(onMqttSubscribe); + mqttClient.onUnsubscribe(onMqttUnsubscribe); + mqttClient.onMessage(onMqttMessage); + mqttClient.setServer(MQTT_HOST, MQTT_PORT); + mqttClient.setCredentials(BROKER_USER, BROKER_PASS); + connectToWifi(); +*/ +} + +void loop() { +//readBME280(); + lv_task_handler(); // let the GUI do its work + lv_tick_inc(5); // tell LVGL how much time has passed + delay(5); // let this time pass +} \ No newline at end of file diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..e69001d --- /dev/null +++ b/src/main.h @@ -0,0 +1,16 @@ +#ifndef MAIN_H +#define MAIN_H + +extern "C" { + #include "freertos/FreeRTOS.h" + #include "freertos/timers.h" +} + +#ifdef MAIN +TimerHandle_t mqttReconnectTimer; +TimerHandle_t wifiReconnectTimer; +#else +extern TimerHandle_t mqttReconnectTimer; +extern TimerHandle_t wifiReconnectTimer; +#endif +#endif \ No newline at end of file diff --git a/src/mqtt.cpp b/src/mqtt.cpp new file mode 100644 index 0000000..fdf3965 --- /dev/null +++ b/src/mqtt.cpp @@ -0,0 +1,61 @@ +#define MQTT + +#include "mqtt.h" + +void connectToMqtt() { + Serial.println("Connecting to MQTT..."); + mqttClient.connect(); +} + +void onMqttConnect(bool sessionPresent) { + Serial.println("Connected to MQTT."); + /*Serial.print("Session present: "); + Serial.println(sessionPresent);*/ + + // Subscribe to topic "message" when it connects to the broker + uint16_t packetIdSub = mqttClient.subscribe(MQTT_TOPIC_MESSAGE, 2); + //Serial.print("Subscribing at QoS 2, packetId: "); + //Serial.println(packetIdSub); +} + +void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) { + Serial.println("Disconnected from MQTT."); + + if (WiFi.isConnected()) { + xTimerStart(mqttReconnectTimer, 0); + } +} + +void onMqttSubscribe(uint16_t packetId, uint8_t qos) { + /*Serial.println("Subscribe acknowledged."); + Serial.print(" packetId: "); + Serial.println(packetId); + Serial.print(" qos: "); + Serial.println(qos);*/ +} + +void onMqttUnsubscribe(uint16_t packetId) { + /*Serial.println("Unsubscribe acknowledged."); + Serial.print(" packetId: "); + Serial.println(packetId);*/ +} + +JsonDocument doc; + +void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) { + // Do whatever you want when you receive a message + // Save the message in a variable + String received_message; + for (int i = 0; i < len; i++) { + Serial.println((char)payload[i]); + received_message += (char)payload[i]; + } + // Display the text message on the display receive from the MQTT topic "message" + if (strcmp(topic, MQTT_TOPIC_MESSAGE) == 0) { + // deserializeJson(doc, received_message); + // String temp = doc["temperature"]; + // String hum = doc["humidity"]; + // received_message = "Temperature: " + temp + "°C\nHumidity: " + hum + "%"; + // lv_label_set_text(mqtt_text_label, received_message.c_str()); + } +} diff --git a/src/mqtt.h b/src/mqtt.h new file mode 100644 index 0000000..ad5a8c2 --- /dev/null +++ b/src/mqtt.h @@ -0,0 +1,31 @@ +#ifndef MQTT_H +#define MQTT_H + +#include +#include +#include +#include "main.h" + +#define MQTT_HOST IPAddress(192,168,178,92) // MQTT BROKER IP ADDRESS +//#define MQTT_HOST "example.com" // MQTT BROKER URL +#define MQTT_PORT 1883 +#define BROKER_USER "rxf" +#define BROKER_PASS "Tux4S!ech" + +#define MQTT_TOPIC_MESSAGE "zigbee2mqtt/Temp_Feuchte_Mini" + +#ifdef MQTT +AsyncMqttClient mqttClient; +#else +extern AsyncMqttClient mqttClient; +#endif + +void connectToMqtt(); +void onMqttConnect(bool sessionPresent); +void onMqttDisconnect(AsyncMqttClientDisconnectReason reason); +void onMqttSubscribe(uint16_t packetId, uint8_t qos); +void onMqttUnsubscribe(uint16_t packetId); +void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total); + + +#endif \ No newline at end of file diff --git a/src/weifi.cpp b/src/weifi.cpp new file mode 100644 index 0000000..d4aa04c --- /dev/null +++ b/src/weifi.cpp @@ -0,0 +1,28 @@ +#define WEIFI + +#include "weifi.h" +#include "mqtt.h" + + +void connectToWifi() { + Serial.println("Connecting to Wi-Fi..."); + WiFi.begin(ssid, password); +} + +void WiFiEvent(WiFiEvent_t event) { + Serial.printf("[WiFi-event] event: %d\n", event); + switch(event) { + case ARDUINO_EVENT_WIFI_STA_GOT_IP: + Serial.println("WiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); + connectToMqtt(); + break; + case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: + Serial.println("WiFi lost connection"); + xTimerStop(mqttReconnectTimer, 0); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi + xTimerStart(wifiReconnectTimer, 0); + break; + } +} + diff --git a/src/weifi.h b/src/weifi.h new file mode 100644 index 0000000..19a0faf --- /dev/null +++ b/src/weifi.h @@ -0,0 +1,19 @@ +#ifndef WEIFI_H +#define WEIFI_H + +#include +#include "main.h" + +#ifdef WEIFI +const char* ssid = "Mizar"; +const char* password = "RingNebelM57"; +#endif + + +// #warning "You need to set the SSID and PASSWORD in weifi.h" + +void connectToWifi(); +void WiFiEvent(WiFiEvent_t event); + + +#endif \ No newline at end of file