Универсальный логгер для Arduino и ESPxx

Представляю Вашему вниманию еще одну маленькую библиотечку. Для чего она нужна?

Пожалуй самый популярный способ “отладки” программ для Arduino – добавление в код скетча текстовых отладочных сообщений, а затем их отслеживание через подключение по COM-порту. Что-то вроде этого:

HTTPClient https;
if (https.begin(wifiClient, httpRequest)) { 
  int httpCode = https.GET();
  if (httpCode > 0) {
   if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
     result = true;
     Serial.printf("TLG :: Send \"%s\": OK (%d)\n", message.c_str(), httpCode);
   }
   else {
    Serial.printf("TLG :: Send \"%s\": FAILED (%d) %s\n", message.c_str(), httpCode, https.errorToString(httpCode).c_str());
   };
  } 
  else {
    Serial.println(F("TLG :: Send FAILED: Unable to connect!"));
  };
  https.end();
} 
else {
 Serial.println(F("TLG :: Send FAILED: Unable to create HTTPS client!"));
};

Код содержит множество отладочных Serial.println(…), позволяющих определить, на каком этапе что пошло не так. Все это просто и хорошо, но ровно до того момента, когда устройство оказывается полностью отлажено и собрано, то есть готово “в продакшен”. В “боевой” обстановке устройство обычно работает вдали от компьютера и вывод в serial только мешает – занимает и процессорные ресурсы, и память. Хорошо бы иметь возможность отключать вывод отладочных сообщений, а при возможных доработках проекта – включать.

Именно такой принцип заложен в библиотеку, которая “встроена” в Framework Arduino для ESP32: “esp32-hal-log.h” (в фреймворке ESP-IDF есть более “навороченная” версия – “esp_log.h”). Причем отключать “отладку” можно “частями” – чем ниже заданный уровень – тем меньше сообщений Вы увидите. Например: ничего, только ошибки, ошибки + предупреждения, ошибки + предупреждения + сообщения и т.д. Большая часть построена на макросах, а это означает, что сообщения выше заданного уровня будут полностью исключены из кода. Очень удобно. И достаточно просто.

 

Так зачем же еще изобретать велосипед? Есть несколько “но”:

  • Во-первых, включив уровень “DEBUG” в настройках проекта, Вы увидите не только “свои” сообщения, но и кучу отладочных сообщений из всех подключенных библиотек фреймворка. Хотелось бы как-то разделить все-таки.
  • Во-вторых, эти библиотеки не будут работать на ESP8266, и уж тем более на AVR. А из-за этого код какой-нибудь “своей” библиотеки перестает работать на другом контроллере только из-за отладки. Хотелось бы какого-то однообразия.
  • Ну и наконец – Вы не сможете изменить настройки sdkconfig.h, если используется только “framework-arduinoespressif32”, он поставляется уже сконфигурированным.

Исходя из этого мне ничего не оставалось, кроме как самым наглейшим образом передрать код “esp32-hal-log.h”, портировать его на ESP8266 и AVR, и сделать отдельные настройки для всего этого.

Как использовать

Есть несколько уровней отладочных сообщений:

  • RLOG_LEVEL_NONE – Сообщения не выводятся
  • RLOG_LEVEL_ERROR – Критические ошибки, программный модуль не может восстановиться самостоятельно
  • RLOG_LEVEL_WARN – Состояния ошибки, из которых были приняты меры по устранению
  • RLOG_LEVEL_INFO – Информационные сообщения, описывающие нормальный ход событий
  • RLOG_LEVEL_DEBUG – Дополнительная информация, которая не требуется для нормального использования (значения, указатели, размеры и т.д.).
  • RLOG_LEVEL_VERBOSE – Большие фрагменты отладочной информации или частые сообщения, которые потенциально могут переполнить вывод.

Им соответствуют несколько функций для вывода этих сообщений:

  • rlog_e(tag, format, …) – Сообщения уровня RLOG_LEVEL_ERROR
  • rlog_w(tag, format, …) – Сообщения уровня RLOG_LEVEL_WARN
  • rlog_i(tag, format, …) – Сообщения уровня RLOG_LEVEL_INFO
  • rlog_d(tag, format, …) – Сообщения уровня RLOG_LEVEL_DEBUG
  • rlog_v(tag, format, …) – Сообщения уровня RLOG_LEVEL_VERBOSE

где: tag – идентификатор, с помощью которого удобно обозначать модуль, откуда пришло сообщение (например “mqtt” или “telegram”) format – собственно сообщение с символами форматирования (или без них) – переменные, передаваемые в строку форматирования (например “Value = %d\n”, 10). Их может и не быть вовсе.

Соответственно, чем выше уровень отладки в Вашем проекте, тем больше сообщений Вы увидите.
Уровень отладки задается с помощью определения #define CONFIG_RLOG_PROJECT_LEVEL RLOG_LEVEL_XXXX, где RLOG_LEVEL_XXXX – этот самый уровень и есть. Кроме этого, есть возможность включить вывод системного времени и цветных ASCII-кодов в сообщения. Эти опции также включаются с помощью макросов.
Например при CONFIG_RLOG_PROJECT_LEVEL == RLOG_LEVEL_INFO в код попадут только макросы-функции rlog_e, rlog_w, rlog_i, а остальные будут игнорированы.
Для CONFIG_RLOG_PROJECT_LEVEL == RLOG_LEVEL_DEBUG будут отображаться ещё и rlog_d.
А при CONFIG_RLOG_PROJECT_LEVEL == RLOG_LEVEL_NONE все отладочные сообщения будет исключены.

Настройка уровня вывода

Осталось придумать, как определить этот самый CONFIG_RLOG_PROJECT_LEVEL

Если весь Ваш код содержится в одном файле – то с этим не будет никаких проблем. Просто добавьте воды #define CONFIG_RLOG_PROJECT_LEVEL RLOG_LEVEL_INFO в начале файла и проблема будет решена.

Сложнее, если Вы будете дробить код по разным файлам. В этом случае целесообразно вынести определения макросов в отдельный файл, например “project_config.h”. Если все файлы проекта находятся в одной папке, то проблем не возникнет.

Проблема будет, если Вы будете подключать какие-то библиотеки, которые находятся в каталогах, отличных от каталога проекта (общие библиотеки, которые используется в нескольких проектах одновременно). В этом случае компилятор при сборке не найдет Ваш “project_config.h”. Нужно ему подсказать, где искать. В PlatformIO это можно сделать с помощью опции -Iкаталог, например так:

[env]
build_flags = -Isrc 

Вуаля. При компиляции библиотек компилятор обязательно заглянет в каталог src, найдет Ваш файл “project_config.h” и подключит его к коду.

А вот в Arduino IDE я не нашел другого выхода, кроме как свалить все в одну кучу и хорошенько перемешать, то есть скопировать все библиотеки в каталог проекта. Впрочем, я не сильно и старался.


Примеры

Примеры для различных платформ и фреймворков Вы можете найти в архиве с исходниками (см. ссылку в конце статьи) в каталоге examples.

#include "Arduino.h"
#include "project_config.h"
#include "rLog.h"

void setup() {
  // put your setup code here, to run once:
  Serial.begin(19200);
  Serial.println();

  rlog_v("DEMO", "Test message, level: %s", "VERBOSE");
  rlog_d("DEMO", "Test message, level: %s", "DEBUG");
  rlog_i("DEMO", "Test message, level: %s", "INFORMATION");
  rlog_w("DEMO", "Test message, level: %s", "WARNING");
  rlog_e("DEMO", "Test message, level: %s", "ERROR");
}

void loop() {
  // put your main code here, to run repeatedly:
  // nothing
}

Результаты компиляции для различных платформ:

Arduino Nano + Framework Arduino

Результаты компиляции для Arduini Nano + Framework Arduino


Тестовый вывод для Arduini Nano + Framework Arduino

ESP8266 + Framework Arduino

Результаты компиляции для ESP8266 + Framework Arduino


Тестовый вывод для ESP8266 + Framework Arduino

ESP32 + Framework Arduino

Результаты компиляции для ESP32 + Framework Arduino


Тестовый вывод для ESP32 + Framework Arduino

ESP32 + Framework ESP-IDF

Результаты компиляции для ESP32 + Framework ESP-IDF


Тестовый вывод для ESP32 + Framework ESP-IDF



Скачать библиотеку:

В архиве Вы также найдете примеры скетча для Arduino IDE и PlatformIO – загляните в папку examples

Значок

rLog :: библиотека и демо-проекты для Arduino & PlatformIO

Библиотека для вывода отладочных сообщений + демонстрационные проекты для PlatformIO и ArduinoIDE.


✳️ Другие мои библиотеки для PlatformIO и ArduinoIDE

Благодарю за внимание.


Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *