espd

ESP32_EMU_BT_V.3.10 with push button

May 26th, 2025 (edited)
17
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 21.39 KB | None | 0 0
  1. #include <Arduino.h>
  2. #define LV_COLOR_16_SWAP 0
  3. #include <lvgl.h>
  4. #include <TFT_eSPI.h>
  5. #include "BluetoothSerial.h"
  6. #include <string>
  7. #include <stdexcept>
  8. using namespace std;
  9.  
  10. //#define USE_NAME
  11. const char *pin = "1234";
  12. String myBtName = "ESP32-BT-Master-1";
  13.  
  14. #if !defined(CONFIG_BT_SPP_ENABLED)
  15. #error Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip.
  16. #endif
  17.  
  18. BluetoothSerial SerialBT;
  19.  
  20. #ifdef USE_NAME
  21. String slaveName = "EMUCANBT_SPP";
  22. #else
  23. uint8_t address[6] = { 0x98, 0xDA, 0x20, 0x02, 0xBE, 0xA4 };
  24. #endif
  25.  
  26. const int backLightPin = 27;
  27. const int buzzerPin = 22;
  28. bool buzzerOn = false;
  29. bool btIconSts = false;
  30. static lv_style_t style_bt;
  31. static bool style_initialized = false;
  32.  
  33. int rpm;
  34. int spd;
  35. float afr;
  36. float mapR;
  37. float boost;
  38. int tps;
  39. int clt;
  40. int ign;
  41. int inj;
  42. float bat;
  43. int cel;
  44.  
  45. static const uint16_t screenWidth = 320;
  46. static const uint16_t screenHeight = 240;
  47.  
  48. TFT_eSPI tft = TFT_eSPI();
  49.  
  50. unsigned long previousMillis = 0;
  51. const unsigned long reconnectInterval = 5000;
  52.  
  53. LV_FONT_DECLARE(lv_font_montserrat_20);
  54. LV_FONT_DECLARE(lv_font_montserrat_22);
  55. LV_FONT_DECLARE(lv_font_montserrat_28);
  56.  
  57. lv_obj_t *bt_icon_label;
  58.  
  59. // Display & LVGL setup
  60. static lv_disp_draw_buf_t draw_buf;
  61. static lv_color_t buf[LV_HOR_RES_MAX * 40];
  62.  
  63. #define NUM_TABS 3
  64. #define TAB_BUTTON_PIN 21
  65. const unsigned long debounceDelay = 50;
  66. static unsigned long lastDebounceTime = 0;
  67. static bool lastButtonState = HIGH;
  68. int currentTab = 0;
  69. lv_obj_t *tabview;
  70. lv_obj_t *tabs[NUM_TABS];
  71. const char *tab_titles[NUM_TABS] = {"1", "2", "3"};
  72. lv_obj_t *tables[NUM_TABS];
  73.  
  74. void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
  75.   uint16_t w = area->x2 - area->x1 + 1;
  76.   uint16_t h = area->y2 - area->y1 + 1;
  77.  
  78.   tft.startWrite();
  79.   tft.setAddrWindow(area->x1, area->y1, w, h);
  80.   tft.pushColors((uint16_t *)&color_p->full, w * h, true);
  81.   tft.endWrite();
  82.  
  83.   lv_disp_flush_ready(disp);
  84. }
  85.  
  86. // Initialize LVGL Table
  87. void create_table() {
  88.   tabview = lv_tabview_create(lv_scr_act(), LV_DIR_TOP, 0);
  89.   lv_obj_t *tab_btns = lv_tabview_get_tab_btns(tabview);
  90.   lv_obj_add_flag(tab_btns, LV_OBJ_FLAG_HIDDEN);
  91.   lv_obj_set_style_text_opa(tabview, LV_OPA_COVER, 0);
  92.   lv_obj_clear_flag(lv_scr_act(), LV_OBJ_FLAG_SCROLLABLE);
  93.  
  94.   lv_obj_clear_flag(tabview, LV_OBJ_FLAG_SCROLLABLE);
  95.   lv_obj_set_scrollbar_mode(tabview, LV_SCROLLBAR_MODE_OFF);
  96.  
  97.   static lv_style_t style_cell0;
  98.   lv_style_init(&style_cell0);
  99.   lv_style_set_pad_top(&style_cell0, 10);
  100.   lv_style_set_pad_bottom(&style_cell0, 10);
  101.   lv_style_set_pad_left(&style_cell0, 2);
  102.   lv_style_set_pad_right(&style_cell0, 2);
  103.  
  104.   static lv_style_t style_cell1;
  105.   lv_style_init(&style_cell1);
  106.   lv_style_set_pad_top(&style_cell1, 19);
  107.   lv_style_set_pad_bottom(&style_cell1, 19);
  108.   lv_style_set_pad_left(&style_cell1, 2);
  109.   lv_style_set_pad_right(&style_cell1, 1);
  110.  
  111.   for(int i = 0; i < NUM_TABS; i++) {
  112.     tabs[i] = lv_tabview_add_tab(tabview, tab_titles[i]);
  113.     tables[i] = lv_table_create(tabs[i]);
  114.     lv_obj_t *table = tables[i];
  115.  
  116.     lv_obj_clear_flag(tabs[i], LV_OBJ_FLAG_SCROLLABLE);
  117.     lv_obj_set_scrollbar_mode(tabs[i], LV_SCROLLBAR_MODE_OFF);
  118.    
  119.     lv_obj_clear_flag(table, LV_OBJ_FLAG_SCROLLABLE);
  120.     lv_obj_set_scrollbar_mode(table, LV_SCROLLBAR_MODE_OFF);
  121.  
  122.     lv_obj_align(table, LV_ALIGN_CENTER, -1, 0);
  123.     lv_obj_set_style_text_opa(table, LV_OPA_COVER, 0);
  124.     lv_obj_set_style_bg_color(lv_scr_act(), lv_color_make(30, 30, 30), LV_PART_MAIN);
  125.     lv_obj_set_style_text_color(table, lv_color_white(), LV_PART_ITEMS);
  126.     lv_obj_set_style_bg_color(table, lv_color_make(30, 30, 30), LV_PART_MAIN);
  127.  
  128.     lv_table_set_col_width(table, 0, 53);
  129.     lv_table_set_col_width(table, 1, 105);
  130.     lv_table_set_col_width(table, 2, 47);
  131.     lv_table_set_col_width(table, 3, 115);
  132.  
  133.     lv_obj_set_style_border_width(table, 1, LV_PART_ITEMS);
  134.     lv_obj_set_style_border_color(table, lv_color_white(), LV_PART_ITEMS);
  135.     lv_obj_set_style_border_side(table, LV_BORDER_SIDE_FULL, LV_PART_ITEMS);
  136.  
  137.     if(i == 0) {
  138.       lv_obj_set_style_text_font(table, &lv_font_montserrat_20, LV_PART_ITEMS);
  139.       lv_obj_add_style(table, &style_cell0, LV_PART_ITEMS);
  140.       lv_table_set_col_cnt(table, 4);
  141.       lv_table_set_row_cnt(table, 6);
  142.    
  143.       lv_table_add_cell_ctrl(table, 5, 1, LV_TABLE_CELL_CTRL_MERGE_RIGHT);
  144.       lv_table_add_cell_ctrl(table, 5, 2, LV_TABLE_CELL_CTRL_MERGE_RIGHT);
  145.       lv_table_add_cell_ctrl(table, 5, 3, LV_TABLE_CELL_CTRL_MERGE_RIGHT);
  146.    
  147.       lv_table_set_cell_value(table, 0, 0, "RPM");
  148.       lv_table_set_cell_value(table, 0, 2, "SPD");
  149.       lv_table_set_cell_value(table, 1, 0, "AFR");
  150.       lv_table_set_cell_value(table, 1, 2, "CLT");
  151.       lv_table_set_cell_value(table, 2, 0, "TPS");
  152.       lv_table_set_cell_value(table, 2, 2, "BAT");
  153.       lv_table_set_cell_value(table, 3, 0, "MAP");
  154.       lv_table_set_cell_value(table, 3, 2, "BST");
  155.       lv_table_set_cell_value(table, 4, 0, "INJ");
  156.       lv_table_set_cell_value(table, 4, 2, "IGN");
  157.       lv_table_set_cell_value(table, 5, 0, "CEL");
  158.    
  159.       lv_obj_add_event_cb(table, my_table_event_cb, LV_EVENT_DRAW_PART_BEGIN, NULL);
  160.       lv_obj_add_event_cb(table, table_event_cb_bg, LV_EVENT_DRAW_PART_BEGIN, NULL);
  161.     } else if (i == 1) {
  162.       lv_obj_set_style_text_font(table, &lv_font_montserrat_22, LV_PART_ITEMS);
  163.       lv_obj_add_style(table, &style_cell1, LV_PART_ITEMS);
  164.       lv_table_set_col_cnt(table, 4);
  165.       lv_table_set_row_cnt(table, 4);
  166.    
  167.       lv_table_add_cell_ctrl(table, 3, 1, LV_TABLE_CELL_CTRL_MERGE_RIGHT);
  168.       lv_table_add_cell_ctrl(table, 3, 2, LV_TABLE_CELL_CTRL_MERGE_RIGHT);
  169.       lv_table_add_cell_ctrl(table, 3, 3, LV_TABLE_CELL_CTRL_MERGE_RIGHT);
  170.    
  171.       lv_table_set_cell_value(table, 0, 0, "RPM");
  172.       lv_table_set_cell_value(table, 0, 2, "SPD");
  173.       lv_table_set_cell_value(table, 1, 0, "AFR");
  174.       lv_table_set_cell_value(table, 1, 2, "BST");
  175.       lv_table_set_cell_value(table, 2, 0, "TPS");
  176.       lv_table_set_cell_value(table, 2, 2, "BAT");
  177.       lv_table_set_cell_value(table, 3, 0, "CEL");
  178.    
  179.       lv_obj_add_event_cb(table, my_table_event_cb2, LV_EVENT_DRAW_PART_BEGIN, NULL);
  180.       lv_obj_add_event_cb(table, table_event_cb_bg2, LV_EVENT_DRAW_PART_BEGIN, NULL);
  181.     } else if (i == 2) {
  182.       lv_obj_set_style_text_font(table, &lv_font_montserrat_22, LV_PART_ITEMS);
  183.       lv_obj_add_style(table, &style_cell1, LV_PART_ITEMS);
  184.       lv_table_set_col_cnt(table, 4);
  185.       lv_table_set_row_cnt(table, 4);
  186.    
  187.       lv_table_add_cell_ctrl(table, 3, 1, LV_TABLE_CELL_CTRL_MERGE_RIGHT);
  188.       lv_table_add_cell_ctrl(table, 3, 2, LV_TABLE_CELL_CTRL_MERGE_RIGHT);
  189.       lv_table_add_cell_ctrl(table, 3, 3, LV_TABLE_CELL_CTRL_MERGE_RIGHT);
  190.    
  191.       lv_table_set_cell_value(table, 0, 0, "RPM");
  192.       lv_table_set_cell_value(table, 0, 2, "SPD");
  193.       lv_table_set_cell_value(table, 1, 0, "AFR");
  194.       lv_table_set_cell_value(table, 1, 2, "CLT");
  195.       lv_table_set_cell_value(table, 2, 0, "INJ");
  196.       lv_table_set_cell_value(table, 2, 2, "IGN");
  197.       lv_table_set_cell_value(table, 3, 0, "CEL");
  198.    
  199.       lv_obj_add_event_cb(table, my_table_event_cb2, LV_EVENT_DRAW_PART_BEGIN, NULL);
  200.       lv_obj_add_event_cb(table, table_event_cb_bg3, LV_EVENT_DRAW_PART_BEGIN, NULL);
  201.     }
  202.   }
  203.   create_bt_icon();
  204.   lv_timer_handler();
  205. }
  206.  
  207. void setup() {
  208.   tft.init();
  209.   pinMode(backLightPin, OUTPUT);
  210.   digitalWrite(backLightPin, LOW);
  211.   uint16_t darkGray = ((30 & 0xF8) << 8) | ((30 & 0xFC) << 3) | (30 >> 3);
  212.   tft.fillScreen(darkGray);
  213.   tft.setRotation(1);
  214.   Serial.begin(1000000);
  215.  
  216.   pinMode(buzzerPin, OUTPUT);
  217.  
  218.   // Initialize LVGL
  219.   lv_init();
  220.   lv_refr_now(NULL);
  221.   lv_disp_draw_buf_init(&draw_buf, buf, NULL, LV_HOR_RES_MAX * 10);
  222.  
  223.   static lv_disp_drv_t disp_drv;
  224.   lv_disp_drv_init(&disp_drv);
  225.   disp_drv.hor_res = screenWidth;
  226.   disp_drv.ver_res = screenHeight;
  227.   disp_drv.flush_cb = my_disp_flush;
  228.   disp_drv.draw_buf = &draw_buf;
  229.   lv_disp_drv_register(&disp_drv);
  230.  
  231.   SerialBT.begin(myBtName, true);
  232.  
  233.   create_table();
  234.   digitalWrite(backLightPin, HIGH);
  235.   connectToBt();
  236.  
  237.   pinMode(TAB_BUTTON_PIN, INPUT);
  238.  
  239. }
  240.  
  241. void connectToBt() {
  242.   bool connected;
  243.   #ifndef USE_NAME
  244.     SerialBT.setPin(pin);
  245.   #endif
  246.  
  247.   #ifdef USE_NAME
  248.     connected = SerialBT.connect(slaveName);
  249.   #else
  250.     connected = SerialBT.connect(address);
  251.   #endif
  252.  
  253.   if (connected) {
  254.     Serial.println("Connected Successfully!");
  255.   } else {
  256.     Serial.println("Initial connect failed. Will retry in loop...");
  257.   }
  258.   update_bt_icon_color(SerialBT.hasClient(), false);
  259. }
  260.  
  261. static uint8_t frame[5];
  262. static int frameIndex = 0;
  263.  
  264. void loop() {
  265.   uint8_t channel;
  266.   uint16_t value;
  267.   int chData;
  268.   unsigned long currentMillis = millis();
  269.  
  270.   if (!SerialBT.connected()) {
  271.     // Attempt reconnection every 5 seconds
  272.     if (currentMillis - previousMillis >= reconnectInterval) {
  273.       previousMillis = currentMillis;
  274.       connectToBt();
  275.     }
  276.   }
  277.  
  278.   update_bt_icon_color(SerialBT.hasClient(), false);
  279.  
  280.   // Wait until at least 5 bytes are available
  281.  // while (SerialBT.available() >= 5) {
  282.     frame[frameIndex++] = SerialBT.read();
  283.  
  284.   if (frameIndex == 5) {
  285.  
  286.     channel = frame[0];
  287.     value = (frame[2] << 8) | frame[3];
  288.     chData = static_cast<int>(channel);
  289.     if (chData == 1) {
  290.       rpm = static_cast<int>(value);
  291.       lv_table_set_cell_value(tables[0], 0, 1, String(rpm).c_str());
  292.       lv_table_set_cell_value(tables[1], 0, 1, String(rpm).c_str());
  293.       lv_table_set_cell_value(tables[2], 0, 1, String(rpm).c_str());
  294.     } else if (chData == 28) {
  295.       spd = (static_cast<int>(value) / 2.8);
  296.       lv_table_set_cell_value(tables[0], 0, 3, (String(spd) + " KM/H").c_str());
  297.       lv_table_set_cell_value(tables[1], 0, 3, (String(spd) + " KM/H").c_str());
  298.       lv_table_set_cell_value(tables[2], 0, 3, (String(spd) + " KM/H").c_str());
  299.     } else if (chData == 12) {
  300.       afr = (static_cast<float>(value) / 10);
  301.       lv_table_set_cell_value(tables[0], 1, 1, String(afr).c_str());
  302.       lv_table_set_cell_value(tables[1], 1, 1, String(afr).c_str());
  303.       lv_table_set_cell_value(tables[2], 1, 1, String(afr).c_str());
  304.     } else if (chData == 2) {
  305.       mapR = (static_cast<float>(value) / 100);
  306.       boost = (mapR - 1.0132f);
  307.       lv_table_set_cell_value(tables[0], 3, 1, (String(mapR) + " BAR").c_str());
  308.       lv_table_set_cell_value(tables[0], 3, 3, (String(boost) + " BAR").c_str());
  309.       lv_table_set_cell_value(tables[1], 1, 3, (String(boost) + " BAR").c_str());
  310.     } else if (chData == 3) {
  311.       tps = static_cast<int>(value);
  312.       lv_table_set_cell_value(tables[0], 2, 1, (String(tps) + " %").c_str());
  313.       lv_table_set_cell_value(tables[1], 2, 1, (String(tps) + " %").c_str());
  314.     } else if (chData == 24) {
  315.       clt = static_cast<int>(value);
  316.       lv_table_set_cell_value(tables[0], 1, 3, (String(clt) + " °C").c_str());
  317.       lv_table_set_cell_value(tables[2], 1, 3, (String(clt) + " °C").c_str());
  318.     } else if (chData == 6) {
  319.       ign = (static_cast<int>(value) / 2);
  320.       lv_table_set_cell_value(tables[0], 4, 3, (String(ign) + " °").c_str());
  321.       lv_table_set_cell_value(tables[2], 2, 3, (String(ign) + " °").c_str());
  322.     } else if (chData == 19) {
  323.       inj = (static_cast<int>(value) / 2);
  324.       lv_table_set_cell_value(tables[0], 4, 1, (String(inj) + " %").c_str());
  325.       lv_table_set_cell_value(tables[2], 2, 1, (String(inj) + " %").c_str());
  326.     } else if (chData == 5) {
  327.       bat = (static_cast<float>(value) / 37);
  328.       lv_table_set_cell_value(tables[0], 2, 3, (String(bat) + " V").c_str());
  329.       lv_table_set_cell_value(tables[1], 2, 3, (String(bat) + " V").c_str());
  330.     } else if (chData == 255) {
  331.       cel = decodeCheckEngine(value);
  332.     }
  333.     frameIndex = 0;
  334.   }
  335.  // }
  336.  
  337.   buzzerOn = (cel > 0 || clt > 105 || rpm > 7000 || boost > 1.10 || (bat < 12.00 && bat > 1.00));
  338.   digitalWrite(buzzerPin, (millis() % 600 < 300) && buzzerOn);
  339.  
  340.   lv_obj_invalidate(tables[0]);
  341.   lv_obj_invalidate(tables[1]);
  342.   lv_obj_invalidate(tables[2]);
  343.  
  344.   bool currentButtonState = digitalRead(TAB_BUTTON_PIN);
  345.  
  346.   if (currentButtonState != lastButtonState) {
  347.     lastDebounceTime = millis();
  348.   }
  349.  
  350.   if ((millis() - lastDebounceTime) > debounceDelay) {
  351.     if (lastButtonState == HIGH && currentButtonState == LOW) {
  352.     int currentTab = lv_tabview_get_tab_act(tabview);
  353.     currentTab = (currentTab + 1) % NUM_TABS;
  354.     lv_tabview_set_act(tabview, currentTab, LV_ANIM_OFF);
  355.     }
  356.   }
  357.  
  358.   lastButtonState = currentButtonState;
  359.  
  360.  
  361.   lv_timer_handler();
  362. }
  363.  
  364. int decodeCheckEngine(uint16_t value) {
  365.   int cel_codes = 0; string cel_names = "";
  366.   if (value == 0) {
  367.     return 0;
  368.   }
  369.   else {
  370.     if (value & (1 << 0)) {
  371.       cel_codes++;  // Bit 0
  372.       cel_names = "CLT ";
  373.     }
  374.     if (value & (1 << 1)) {
  375.       //cel_codes++;  // Bit 1
  376.       //cel_names += "IAT ";
  377.     }
  378.     if (value & (1 << 2)) {
  379.       cel_codes++;  // Bit 2
  380.       cel_names += "MAP ";
  381.     }
  382.     if (value & (1 << 3)) {
  383.       cel_codes++;  // Bit 3
  384.       cel_names += "WBO ";
  385.     }
  386.     if (value & (1 << 8)) {
  387.       cel_codes++;  // Bit 8
  388.       cel_names += "FF SENSOR ";
  389.     }
  390.     if (value & (1 << 9)) {
  391.       cel_codes++;  // Bit 9
  392.       cel_names += "DBW ";
  393.     }
  394.     if (value & (1 << 10)) {
  395.       cel_codes++;  // Bit 10
  396.       cel_names += "FPR ";
  397.     }
  398.  
  399.     lv_table_set_cell_value(tables[0], 5, 1, cel_names.c_str());
  400.     lv_table_set_cell_value(tables[1], 3, 1, cel_names.c_str());
  401.     lv_table_set_cell_value(tables[2], 3, 1, cel_names.c_str());
  402.     return cel_codes;
  403.   }
  404. }
  405.  
  406. // Cell alignment fix
  407. void my_table_event_cb(lv_event_t * e) {
  408.   lv_obj_t * table = lv_event_get_target(e);
  409.   lv_obj_draw_part_dsc_t * dsc = (lv_obj_draw_part_dsc_t *)lv_event_get_param(e);
  410.  
  411.   if (dsc->part == LV_PART_ITEMS) {
  412.     uint16_t row = dsc->id / lv_table_get_col_cnt(table);
  413.     uint16_t col = dsc->id % lv_table_get_col_cnt(table);
  414.  
  415.     dsc->label_dsc->align = LV_TEXT_ALIGN_LEFT;
  416.     if ((row == 0 && col == 1) || (row == 0 && col == 3) || (row == 1 && col == 1) || (row == 1 && col == 3) || (row == 2 && col == 1) || (row == 2 && col == 3) || (row == 3 && col == 1) || (row == 3 && col == 3) ||
  417.         (row == 4 && col == 1) || (row == 4 && col == 3)) {
  418.       dsc->label_dsc->align = LV_TEXT_ALIGN_RIGHT;
  419.     }
  420.     if (row == 5 && col == 1) {
  421.       dsc->label_dsc->align = LV_TEXT_ALIGN_CENTER;
  422.     }
  423.   }
  424. }
  425.  
  426. // Cell alignment fix
  427. void my_table_event_cb2(lv_event_t * e) {
  428.   lv_obj_t * table = lv_event_get_target(e);
  429.   lv_obj_draw_part_dsc_t * dsc = (lv_obj_draw_part_dsc_t *)lv_event_get_param(e);
  430.  
  431.   if (dsc->part == LV_PART_ITEMS) {
  432.     uint16_t row = dsc->id / lv_table_get_col_cnt(table);
  433.     uint16_t col = dsc->id % lv_table_get_col_cnt(table);
  434.  
  435.     dsc->label_dsc->align = LV_TEXT_ALIGN_LEFT;
  436.     if ((row == 0 && col == 1) || (row == 0 && col == 3) || (row == 1 && col == 1) || (row == 1 && col == 3) || (row == 2 && col == 1) || (row == 2 && col == 3)) {
  437.       dsc->label_dsc->align = LV_TEXT_ALIGN_RIGHT;
  438.     }
  439.     if (row == 3 && col == 1) {
  440.       dsc->label_dsc->align = LV_TEXT_ALIGN_CENTER;
  441.     }
  442.   }
  443. }
  444.  
  445. static void table_event_cb_bg(lv_event_t *e) {
  446.   lv_obj_t *table = lv_event_get_target(e);
  447.   lv_obj_draw_part_dsc_t *dsc = (lv_obj_draw_part_dsc_t *)lv_event_get_param(e);
  448.  
  449.   // Ensure dsc and rect_dsc are valid
  450.   if (!dsc || !dsc->rect_dsc) return;
  451.  
  452.   // Only modify table cell backgrounds
  453.   if (dsc->part == LV_PART_ITEMS) {
  454.     uint16_t row = dsc->id / lv_table_get_col_cnt(table);
  455.     uint16_t col = dsc->id % lv_table_get_col_cnt(table);
  456.  
  457.     const char *value_str = lv_table_get_cell_value(table, row, col);
  458.  
  459.     // Check if value_str is null or empty before conversion
  460.     float value = 0.0f;  // Default value
  461.     if (value_str != nullptr && value_str[0] != '\0') {
  462.       try {
  463.         value = std::stof(value_str);  // Convert string to float safely
  464.       } catch (...) {
  465.         value = 0.0f;  // Handle invalid conversions
  466.       }
  467.     }
  468.  
  469.     // Default cell color
  470.     lv_color_t bg_color = lv_color_make(30, 30, 30);
  471.     lv_color_t text_color = lv_color_white();
  472.  
  473.     if (row == 0 && col == 1 && value > 7000.00) {
  474.       bg_color = lv_color_make(0, 0, 255);
  475.       text_color = lv_color_white();
  476.     }
  477.     if (row == 1 && col == 3 && value > 100.00) {
  478.       bg_color = lv_color_make(0, 0, 255);
  479.       text_color = lv_color_white();
  480.     }
  481.     if (row == 1 && col == 3 && value < 55.00 && value > 01.00) {
  482.       bg_color = lv_color_make(0, 255, 255);
  483.       text_color = lv_color_black();
  484.     }
  485.     if (row == 2 && col == 3 && value < 12.00 && value > 01.00) {
  486.       bg_color = lv_color_make(0, 0, 255);
  487.       text_color = lv_color_white();
  488.     }
  489.     if (row == 3 && col == 3 && value > 1.10) {
  490.       bg_color = lv_color_make(0, 0, 255);
  491.       text_color = lv_color_white();
  492.     }
  493.     if (row == 5 && col == 1 && value_str != nullptr && value_str[0] != '\0') {
  494.       bg_color = lv_color_make(0, 0, 255);
  495.       text_color = lv_color_white();
  496.     }
  497.  
  498.     // Apply background color to the cell
  499.     dsc->rect_dsc->bg_color = bg_color;
  500.     dsc->rect_dsc->bg_opa = LV_OPA_COVER;
  501.     dsc->label_dsc->color = text_color;
  502.   }
  503. }
  504.  
  505. static void table_event_cb_bg2(lv_event_t *e) {
  506.   lv_obj_t *table = lv_event_get_target(e);
  507.   lv_obj_draw_part_dsc_t *dsc = (lv_obj_draw_part_dsc_t *)lv_event_get_param(e);
  508.  
  509.   // Ensure dsc and rect_dsc are valid
  510.   if (!dsc || !dsc->rect_dsc) return;
  511.  
  512.   // Only modify table cell backgrounds
  513.   if (dsc->part == LV_PART_ITEMS) {
  514.     uint16_t row = dsc->id / lv_table_get_col_cnt(table);
  515.     uint16_t col = dsc->id % lv_table_get_col_cnt(table);
  516.  
  517.     const char *value_str = lv_table_get_cell_value(table, row, col);
  518.  
  519.     // Check if value_str is null or empty before conversion
  520.     float value = 0.0f;  // Default value
  521.     if (value_str != nullptr && value_str[0] != '\0') {
  522.       try {
  523.         value = std::stof(value_str);  // Convert string to float safely
  524.       } catch (...) {
  525.         value = 0.0f;  // Handle invalid conversions
  526.       }
  527.     }
  528.  
  529.     // Default cell color
  530.     lv_color_t bg_color = lv_color_make(30, 30, 30);
  531.     lv_color_t text_color = lv_color_white();
  532.  
  533.     if (row == 0 && col == 1 && value > 7000.00) {
  534.       bg_color = lv_color_make(0, 0, 255);
  535.       text_color = lv_color_white();
  536.     }
  537.     if (row == 2 && col == 3 && value < 12.00 && value > 01.00) {
  538.       bg_color = lv_color_make(0, 0, 255);
  539.       text_color = lv_color_white();
  540.     }
  541.     if (row == 1 && col == 3 && value > 1.10) {
  542.       bg_color = lv_color_make(0, 0, 255);
  543.       text_color = lv_color_white();
  544.     }
  545.     if (row == 5 && col == 1 && value_str != nullptr && value_str[0] != '\0') {
  546.       bg_color = lv_color_make(0, 0, 255);
  547.       text_color = lv_color_white();
  548.     }
  549.  
  550.     // Apply background color to the cell
  551.     dsc->rect_dsc->bg_color = bg_color;
  552.     dsc->rect_dsc->bg_opa = LV_OPA_COVER;
  553.     dsc->label_dsc->color = text_color;
  554.   }
  555. }
  556.  
  557. static void table_event_cb_bg3(lv_event_t *e) {
  558.   lv_obj_t *table = lv_event_get_target(e);
  559.   lv_obj_draw_part_dsc_t *dsc = (lv_obj_draw_part_dsc_t *)lv_event_get_param(e);
  560.  
  561.   // Ensure dsc and rect_dsc are valid
  562.   if (!dsc || !dsc->rect_dsc) return;
  563.  
  564.   // Only modify table cell backgrounds
  565.   if (dsc->part == LV_PART_ITEMS) {
  566.     uint16_t row = dsc->id / lv_table_get_col_cnt(table);
  567.     uint16_t col = dsc->id % lv_table_get_col_cnt(table);
  568.  
  569.     const char *value_str = lv_table_get_cell_value(table, row, col);
  570.  
  571.     // Check if value_str is null or empty before conversion
  572.     float value = 0.0f;  // Default value
  573.     if (value_str != nullptr && value_str[0] != '\0') {
  574.       try {
  575.         value = std::stof(value_str);  // Convert string to float safely
  576.       } catch (...) {
  577.         value = 0.0f;  // Handle invalid conversions
  578.       }
  579.     }
  580.  
  581.     // Default cell color
  582.     lv_color_t bg_color = lv_color_make(30, 30, 30);
  583.     lv_color_t text_color = lv_color_white();
  584.  
  585.     if (row == 0 && col == 1 && value > 7000.00) {
  586.       bg_color = lv_color_make(0, 0, 255);
  587.       text_color = lv_color_white();
  588.     }
  589.     if (row == 1 && col == 3 && value > 100.00) {
  590.       bg_color = lv_color_make(0, 0, 255);
  591.       text_color = lv_color_white();
  592.     }
  593.     if (row == 1 && col == 3 && value < 55.00 && value > 01.00) {
  594.       bg_color = lv_color_make(0, 255, 255);
  595.       text_color = lv_color_black();
  596.     }
  597.     if (row == 5 && col == 1 && value_str != nullptr && value_str[0] != '\0') {
  598.       bg_color = lv_color_make(0, 0, 255);
  599.       text_color = lv_color_white();
  600.     }
  601.  
  602.     // Apply background color to the cell
  603.     dsc->rect_dsc->bg_color = bg_color;
  604.     dsc->rect_dsc->bg_opa = LV_OPA_COVER;
  605.     dsc->label_dsc->color = text_color;
  606.   }
  607. }
  608.  
  609. void update_bt_icon_color(bool is_connected, bool firstTime) {
  610.   if(btIconSts != is_connected || firstTime) {
  611.     if (!style_initialized) {
  612.       lv_style_init(&style_bt);
  613.       style_initialized = true;
  614.     }
  615.     if (is_connected) {
  616.       lv_style_set_text_color(&style_bt, lv_color_make(0, 255, 0)); // Green
  617.     } else {
  618.       lv_style_set_text_color(&style_bt, lv_color_make(0, 0, 255)); // Red
  619.     }
  620.     lv_obj_add_style(bt_icon_label, &style_bt, 0);
  621.     btIconSts = is_connected;
  622.   }
  623. }
  624.  
  625. void create_bt_icon() {
  626.   bt_icon_label = lv_label_create(lv_scr_act());
  627.   lv_label_set_text(bt_icon_label, LV_SYMBOL_BLUETOOTH);
  628.   lv_obj_set_style_text_font(bt_icon_label, &lv_font_montserrat_28, LV_PART_MAIN);
  629.   lv_obj_align(bt_icon_label, LV_ALIGN_BOTTOM_RIGHT, -3, -1);
  630.   update_bt_icon_color(SerialBT.hasClient(), true);
  631. }
Advertisement
Add Comment
Please, Sign In to add comment