Ошибка при определении тикера в библиотеке ESP32

Я использую точно такой же фрагмент кода в моей библиотеке ESP8266 (которая работает нормально), но при использовании в библиотеке ESP32 я получаю сообщение об ошибке:

Это соответствующий фрагмент кода:

void myIOT32::_feedTheDog()
{
  _wdtResetCounter++;
  if (_wdtResetCounter >= _wdtMaxRetries)
  {
    sendReset("Dog goes woof");
  }
}
void myIOT32::_startWDT()
{
  wdt.attach(1, std::bind(&myIOT32::_feedTheDog, this)); // Start WatchDog
}

void myIOT32::sendReset(char *header)
{
  char temp[150];

  sprintf(temp, "[%s] - Reset sent", header);

  if (useSerial)
  {
    Serial.println(temp);
  }
  if (strcmp(header, "null") != 0)
  {
    pub_msg(temp);
  }
  delay(1000);
  ESP.restart();
}

и это ошибка:

/home/guy/Documents/git/Arduino/libraries/myIOTesp32/myIOTesp32.cpp: In member function 'void myIOT32::_startWDT()':
/home/guy/Documents/git/Arduino/libraries/myIOTesp32/myIOTesp32.cpp:333:55: error: no matching function for call to 'Ticker::attach(int, std::_Bind_helper<false, void (myIOT32::*)(), myIOT32*>::type)'
   wdt.attach(1, std::bind(&myIOT32::_feedTheDog, this)); // Start WatchDog
                                                       ^

, 👍2


1 ответ


4

Функции прикрепления тикера ESP32 принимают чистые указатели функций с максимум одним типом аргумента, а не std::function/ std::_Bind_helper, который std: :bind производит.

См. код и типы по адресу https://github. com/espressif/arduino-esp32/blob/master/libraries/Ticker/src/Ticker.h#L38.

Однако для ESP8266 используется std::function:

https://github.com/esp8266/Arduino/blob /master/libraries/Ticker/src/Ticker.h#L36

И именно поэтому он работает на ESP8266, а не на ESP32 — либо адаптируйте библиотеку Ticker, либо переделайте свой собственный код, чтобы не использовать функции-члены классов.

Редактировать: вы можете легко переписать свой код, чтобы использовать статическую вспомогательную функцию с одним аргументом (сам объект сторожевого таймера), который затем просто вызывает функцию-член этого объекта. Чтобы это работало, вызываемая функция должна быть общедоступной. Итак, перепишите как

static void watchdog_timer_triggered_helper(myIOT32* watchdog) {
   // должен быть общедоступным!
   watchdog->_feedTheDog();
}

void myIOT32::_feedTheDog()
{
  _wdtResetCounter++;
  if (_wdtResetCounter >= _wdtMaxRetries)
  {
    sendReset("Dog goes woof");
  }
}
void myIOT32::_startWDT()
{
  wdt.attach(1, &watchdog_timer_triggered_helper, this); // Запустить сторожевой таймер
}

void myIOT32::sendReset(char *header)
{
  char temp[150];

  sprintf(temp, "[%s] - Reset sent", header);

  if (useSerial)
  {
    Serial.println(temp);
  }
  if (strcmp(header, "null") != 0)
  {
    pub_msg(temp);
  }
  delay(1000);
  ESP.restart();
}

Поскольку обе версии ESP32 и ESP8266 реализуют

    template<typename TArg>
    void attach(float seconds, void (*callback)(TArg), TArg arg)

шаблонная функция теперь должна работать на обеих платформах.

,

Спасибо за объяснение. Можете ли вы поделиться примером, как переделать?, @Guy . D

@Guy.D смотрите обновление., @Maximilian Gerhardt

@Maximillian - спасибо за ответ. Я боюсь, что вы это немного больше, чем я понимаю :(, и я не люблю копировать ответ без полного понимания. Не могли бы вы объяснить больше или, возможно, более простой ответ (извините...), @Guy . D

@Guy.D, разве вы не написали исходный код с std::bind, который сложнее, чем указатель на функцию, используемый в ответе? В любом случае, я предлагаю почитать о шаблонах C++ (attach() — это шаблонная функция), указателях на чистые функции и std::function в C++. Я бы взял какой-нибудь тихий длинный текст, чтобы полностью объяснить это в своем ответе о_о., @Maximilian Gerhardt

честно говоря, когда я нашел этот ответ для 8266, я просто принял его как заданное решение, не зная, как работает bind для каждой детали.... (стыдно мне :)))...., @Guy . D

@Maximillian - Что ж, после долгих поисков (почти месяца) я не смог найти ни одного поясняющего примера, чтобы понять ваше решение (не часть шаблона). Не могли бы вы сослаться?, @Guy . D