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();
}
};