Hi everyone,
I’ve been working on a little project. Sort of a monitoring device for sensors and smart power relays using MQTT. Think, Home Assistant, but way worse, in every way.
I’ve tried to provide as much info as I could, but if there is anything missing, let me know.
Description
I’ve created a separate class for every device I use, each containing every every object used when creating the panel itself
What MCU/Processor/Board and compiler are you using?
I am using this touch display panel and the code is based on the LVGL Widgets demo provided with it. It is compiled with the Arduino IDE
Video of the issue
Code to reproduce
This is an shortened example of what the class looks like
Essentially, it contains all all LVGL objects, getters, setters and the function to generate the initial panel itself
class TestClass {
private:
lv_style_t style;
lv_obj_t * Panel;
lv_obj_t * DeviceName;
String test = "test";
public:
//GETTERS
lv_obj_t * getPanel() {
return Panel;
}
lv_obj_t * getDeviceName() {
return DeviceName;
}
//SETTERS
void setdeviceName(const char* newContent) {
//lv_label_set_text_fmt(DeviceName , "%s", device["DeviceName"].as<const char*>());
lv_label_set_text(DeviceName, newContent);
}
void updateDevice() {
lv_label_set_text_fmt(DeviceName, "%s",test);
}
void createTestPanel(lv_obj_t * parent, JsonVariant device) {
static lv_style_t style;
lv_style_init(&style);
lv_style_set_flex_flow(&style, LV_FLEX_FLOW_ROW_WRAP);
lv_style_set_flex_main_place(&style, LV_FLEX_ALIGN_SPACE_EVENLY);
lv_style_set_layout(&style, LV_LAYOUT_FLEX);
//create panel
lv_obj_t * panel1 = lv_obj_create(parent);
lv_obj_set_size(panel1, lv_pct(48), LV_SIZE_CONTENT);
lv_obj_set_style_pad_bottom(panel1, 30, 0);
lv_obj_add_style(panel1, &style, 0);
//Device name
lv_obj_t * DeviceName = lv_label_create(panel1);
lv_obj_set_size(DeviceName, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_label_set_text(DeviceName, device["DeviceName"].as<const char*>());
lv_obj_add_style(DeviceName, &style_title, 0);
if (disp_size == DISP_LARGE) {
static lv_coord_t grid1_col_dsc[] = {LV_GRID_FR(1), 20, LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
static lv_coord_t grid1_row_dsc[] = {LV_GRID_FR(1), 20, LV_GRID_CONTENT, LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
lv_obj_set_grid_dsc_array(panel1, grid1_col_dsc, grid1_row_dsc);
lv_obj_set_grid_cell(DeviceName, LV_GRID_ALIGN_START, 0, 1, LV_GRID_ALIGN_START, 0, 1);
}
}
};
This is the code handling MQTT.
Essentially when a message arrives, a new Panel is created using the decoded JSON from the message and is then stored in a Dictionary with DeviceID as the key.
Or, if it already is in the dictionary, it finds the panel by the DeviceID key, and updates the necessary labels and indicators, which should be accessible by the get functions of the class.
And now, the problem itself.
When recieving the first message, the panel is created without any issues. It is also stored in the dictionary.
On the second message, the Panel is found, however, the device always crashes, when accessing the lv_obj_t * label.
I’ve tried updating it via the setter function, outside of the class via the getter function, and so far it has always crashed
I’ve also tried using it without the dictionary, but it still crashed.
I’ve also trying access to other String variables, but that worked fine.
So, I’ve tried to set a private String variable, and then use it to set the label text, which crashed.
I am starting to run out of ideas here.
Dictionary<String, TestClass> TestDict = Dictionary<String, TestClass>();
void onConnectionEstablished() {
client.subscribe("test/+", [] (const String & payload) {
deserializeJson(JSONData, payload);
JsonArray arr = JSONData.as<JsonArray>();
for (JsonVariant value : arr) {
Serial.println(value["DeviceType"].as<const char*>());
String DeviceID = value["DeviceID"].as<String>();
if (value["DeviceType"].as<String>().equals("Test")) {
if (!TestDict.isInDictionary(value["DeviceID"].as<const char*>())) {
testClass testPanel;
testPanel.createTestPanel(t1, value);
TestDict.set(DeviceID, testPanel);
}
else {
Serial.println(TestDict.length());
TestClass UpdatingTest = TestDict.get(DeviceID);
UpdatingTest.setDeviceName(value["DeviceName"].as<const char*>());
//does not work
//lv_label_set_text(UpdatingTest.getDeviceName(), value["DeviceName"].as<const char*>());
//lv_label_set_text(TestDict.get(DeviceID).getDeviceName(), value["DeviceName"].as<const char*>());
//UpdatingTest.updateDevice();
}
}
}
});
}
Crash dump to serial
Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x420adf97 PS : 0x00060730 A0 : 0x82008927 A1 : 0x3fcebbb0
A2 : 0x06ffffff A3 : 0x3d800938 A4 : 0x000000ff A5 : 0x0000ff00
A6 : 0x00ff0000 A7 : 0xff000000 A8 : 0x00656d61 A9 : 0x00efffe3
A10 : 0x00000003 A11 : 0x018c1abc A12 : 0x000000ff A13 : 0x0000ff00
A14 : 0x00ff0000 A15 : 0xff000000 SAR : 0x00000014 EXCCAUSE: 0x0000001c
EXCVADDR: 0x07000007 LBEG : 0x400554b9 LEND : 0x400554dd LCOUNT : 0x82001e7f
Backtrace: 0x420adf94:0x3fcebbb0 0x42008924:0x3fcebbd0 0x420257bd:0x3fcebc00 0x420046ce:0x3fcebc20 0x420047f5:0x3fcebdb0 0x4202b2f9:0x3fcebdd0 0x4202b362:0x3fcebe30 0x4202f115:0x3fcebe50 0x4202b3c8:0x3fcebe90 0x4202b6a6:0x3fcebeb0 0x42002245:0x3fcebed0 0x42033f69:0x3fcebef0