Home > OS >  ESP home using Arduino library
ESP home using Arduino library

Time:07-28

I am about to write a custom ESPHome component. I don't have much experience with C language and I am facing some troubles using external library.

For demonstration, I prepared a simple component class..

class Test: public Component {

public:
    auto t = timer_create_default();

    void setup() override {
        ESP_LOGD("TEST", "Test setup called!");
        t.every(1000, TestLog);
    }
    
    void loop() override {
        ESP_LOGD("TEST", "Test loop called!");
        t.tick();
    }
    
    bool TestLog(void *) {
        ESP_LOGD("TEST", "TestLOG!");
        return true;
    }
}

With this, I receive:

In file included from src\main.cpp:32:0: src\Test.h:7:35: error: non-static data member declared 'auto' auto t = timer_create_default();

I took it from some example where they did not have the class, but I can't find out, how to use it.

The library is:

https://github.com/contrem/arduino-timer/

I can still rewrite it without this timer completely and handle it only in the loop function, but I would like to understand what I am doing wrong.

If I change the return type to Timer<> I got another error:

src\Test.h: In member function 'virtual void Test::setup()': src\Test.h:11:24: error: no matching function for call to 'Timer<>::every(int, )'
t.every(1000, TestLog);

CodePudding user response:

You can not use auto to declare non-static member variables so you need to replace auto with the type returned by timer_create_default().

If you are not sure what type it returns, you can simply use decltype in the declaration:

decltype(timer_create_default()) t = timer_create_default();

If I read the code in the repo correctly, the returned type is Timer<>, so this should also work:

Timer<> t = timer_create_default();

or simply:

Timer<> t;

Also: The function pointer passed to t.every() should be a bool (*)(void*) but TestLog is a non-static member function and the pointer type is bool (Test::*)(void*) - You can fix that by making TestLog static:

class Test: public Component {
public:
    // ...

    static bool TestLog(void *) {
        ESP_LOGD("TEST", "TestLOG!");
        return true;
    }
};

If you want to get the Test instance in the TestLog callback, make the Timer

Timer<TIMER_MAX_TASKS, millis, Test*> t;

and change TestLog:

class Test: public Component {
public:
    // ...

    static bool TestLog(Test* t) {
        ESP_LOGD("TEST", "TestLOG!");
        return true;
    }
};

and in setup():

t.every(1000, TestLog, this);

You'll now get a pointer to the Test instance in the TestLog callback and you can use this to call a non-static member function in Test.

Full example:

class Test : public Component {
public:
    Timer<TIMER_MAX_TASKS, millis, Test*> t;

    void setup() override {
        ESP_LOGD("TEST", "Test setup called!");
        // call the static member function every second:
        t.every(1000, TestLogProxy, this);
    }
    
    void loop() override {
        ESP_LOGD("TEST", "Test loop called!");
        t.tick();
    }

    bool TestLog() {
        ESP_LOGD("TEST", "TestLOG!");
        return true;
    }
    
    static bool TestLogProxy(Test* t) {
        // forward the callback call to the non-static member function:
        return t->TestLog();
    }
};
  • Related