wrap Nextion library into a class

First, if there is an overall better(easier) UI solution for an esp32 based board, I’m all ears.

I am trying to wrap the nextion library (https://github.com/itead/ITEADLIB_Arduino_Nextion/) into a class called Display.

I previously had this working without a class, in a simpler sketch. Now Im trying to port it over and have a couple small issues.

I whittled the class down to something postable. there were about 100 member functions, and they all do something very similar, just wanted to get to the point.

#ifndef __DISPLAY_TEST_H__
#define __DISPLAY_TEST_H__

#include <Nextion.h>

class Display_Test
{
private:
    NexRtc rtc;
    //Lock Page
    NexPage lockPage = NexPage(0, 0, "Lock");

    //Select Page
    NexPage selectPage = NexPage(1, 0, "Select");
    NexButton settingsButton = NexButton(1, 5, "bSettings");
//Settings Page
    NexPage settingsPage = NexPage(6, 0, "Settings");
    NexButton settingsSaveButton = NexButton(6, 1, "bSave");
    NexButton settingsCancelButton = NexButton(6, 2, "bCancel");

    NexTouch *nex_listen_list[7] = {
        &settingsPage,
        &selectPage,
        &lockPage,
        &settingsButton,
        &settingsSaveButton,
        &settingsCancelButton,
        NULL};

    void ButtonSettingRelease(void *);
    void ButtonSettingsSaveRelease(void *);
    void ButtonSettingsCancelRelease(void *);

public:
    Display_Test();
    void begin();
};

#endif /*__DISPLAY_TEST_H__*/
#include "display_test.h"

Display_Test::Display_Test()
{
}
void Display_Test::begin()
{
    Serial2.println("Setting up Display");
    nexInit();
    settingsButton.attachPop(ButtonSettingRelease, &settingsButton); //compiler error 
    settingsSaveButton.attachPop(ButtonSettingsSaveRelease, &settingsSaveButton); //compiler error 
    settingsCancelButton.attachPop(ButtonSettingsCancelRelease, &settingsCancelButton); //compiler error 
}
void Display_Test::ButtonSettingRelease(void *ptr)
{
    settingsPage.show();
}
void Display_Test::ButtonSettingsSaveRelease(void *ptr)
{
   
}
void Display_Test::ButtonSettingsCancelRelease(void *ptr)
{

}

the compiler shows this:
src\display_test.cpp:10:67: error: invalid use of non-static member function
settingsButton.attachPop(ButtonSettingRelease, &settingsButton);

and this:
argument of type “void (Display_Test::*)(void *ptr)” is incompatible with parameter of type “NexTouchEventCb”

for each of the attachPop functions.

this works when not done within a class. Ive tried changing the 2nd variable to static and event const. im not sure what the right thing to do here is. -

A member function has a different type/signature than a global function.

The simple fix in your case is to make everything in your class "static". Note that it requires a bit more work to initialize those static classes.

something like this?:

#ifndef __DISPLAY_TEST_H__
#define __DISPLAY_TEST_H__

#include <Nextion.h>

class Display_Test
{
private:
    NexRtc rtc;
    //Lock Page
    static NexPage lockPage;

    //Select Page
    static NexPage selectPage;
    static NexButton settingsButton;
    //Settings Page
    static NexPage settingsPage;
    static NexButton settingsSaveButton;
    static NexButton settingsCancelButton;

    NexTouch *nex_listen_list[7] = {
        &settingsPage,
        &selectPage,
        &lockPage,
        &settingsButton,
        &settingsSaveButton,
        &settingsCancelButton,
        NULL};

    static void ButtonSettingRelease(void *);
    static void ButtonSettingsSaveRelease(void *);
    static void ButtonSettingsCancelRelease(void *);
    Display_Test() {}

public:
    void begin();
};

#endif /*__DISPLAY_TEST_H__*/
#include "display_test.h"

NexPage Display_Test::lockPage = NexPage(0, 0, "Lock");
NexPage Display_Test::selectPage = NexPage(1, 0, "Select");
NexButton Display_Test::settingsButton = NexButton(1, 5, "bSettings");
NexPage Display_Test::settingsPage = NexPage(6, 0, "Settings");
NexButton Display_Test::settingsSaveButton = NexButton(6, 1, "bSave");
NexButton Display_Test::settingsCancelButton = NexButton(6, 2, "bCancel");


void Display_Test::begin()
{
    Serial2.println("Setting up Display");
    nexInit();
    settingsButton.attachPop(ButtonSettingRelease, &settingsButton);
    settingsSaveButton.attachPop(ButtonSettingsSaveRelease, &settingsSaveButton);
    settingsCancelButton.attachPop(ButtonSettingsCancelRelease, &settingsCancelButton);
}
void Display_Test::ButtonSettingRelease(void *ptr)
{
    settingsPage.show();
}
void Display_Test::ButtonSettingsSaveRelease(void *ptr)
{
}
void Display_Test::ButtonSettingsCancelRelease(void *ptr)
{
}

assuming that the above is correct, I have a second part...

Let's say that I have a bunch of different classes. Heater, Sensor, WiFi, AWS_IOT, etc.

They all need to write to the display class, what structure would be best to do this efficiently?

I think that doing something like this is wrong:

Heater heater();

int currentTemp = heater.getCurrentTemp();
Display::updatePage2Temp(currentTemp); //static

and something like this might not be right either:

class Heater(){

  int Heater::getCurrentTemp(){
    //gets the temp from the sensor

  }
  void Heater::updateDisplay(int currentTemp){
    Display::updatePage2Temp(currentTemp);
  }

}

I would like everything to use the Display, and the Display having a known state (what page it is on)

Then, it's time to learn in deep: https://isocpp.org/wiki/faq/pointers-to-members.

if I'm not back in 24 hours.... I've died.

tell my family I love them.

ok, i read that whole page. I feel as though I was lacking context though.

why would I use a pointer to a member?

I tried my hand at getting this to work and would like feedback if this is the correct way. Since my display class is so large, I just uploaded it to github

https://github.com/hicotton02/BeverageController

I made the display a singleton class. there will only ever be one and only one display, and the ESP32 is dual core, so it seems right.

in the heater class, I reference the display and during the Heater::taskThread() function, I call display->updateHtlTemp(temp);

and I assume in the sensors class, and any other class, I can do the same thing. Is this a supported/correct approach?

Theskaz,

I can't help with wrapping the Nextion libraries into a class, but are you aware that the ITEAD versions are full of bugs? I suggest you use instead Ray Livingston's versions of the Nextion libraries Ray has fixed many of the bugs.

I am actually, I have copied his files before. My nexconfig is a little different. thanks for pointing that out though!

theskaz:
and I assume in the sensors class, and any other class, I can do the same thing. Is this a supported/correct approach?

If it works for you then don’t change it.
The C++ way to handle callback function is using the std::function<> container. But this container has overhead that may not be fit for microcontroller. However as far as I know, ESP does use this a lot to wrap their callback functions.