espd

ESP32_EMU_BT_V.3.08

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