From be3f935575a80e7cb052aefdbae227a6b9a0dce7 Mon Sep 17 00:00:00 2001 From: Pablo2048 Date: Fri, 19 Jan 2024 11:42:39 +0100 Subject: [PATCH] Priprava na release 1.0.0 - moznost presmerovani na seriovy ladici port. --- {src/examples => examples}/ttest/ttest.ino | 0 library.json | 4 +- library.properties | 6 +- .../traceAsyncWebsocket.cpp} | 139 ++++++------- src/asyncWebsocket/traceAsyncWebsocket.hpp | 108 ++++++++++ src/trace.h | 194 +++++++----------- 6 files changed, 256 insertions(+), 195 deletions(-) rename {src/examples => examples}/ttest/ttest.ino (100%) rename src/{trace.cpp => asyncWebsocket/traceAsyncWebsocket.cpp} (63%) create mode 100644 src/asyncWebsocket/traceAsyncWebsocket.hpp diff --git a/src/examples/ttest/ttest.ino b/examples/ttest/ttest.ino similarity index 100% rename from src/examples/ttest/ttest.ino rename to examples/ttest/ttest.ino diff --git a/library.json b/library.json index d771543..53ad06d 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name":"Trace", - "description":"Web based trace debug module", + "description":"Multi-target trace debug module", "keywords":"debug,trace", "authors": { @@ -12,7 +12,7 @@ "type": "git", "url": "https://git.xpablo.cz/pablo2048/Trace.git" }, - "version": "0.0.6", + "version": "1.0.0", "license": "MIT", "frameworks": "arduino", "platforms": ["espressif8266","espressif32"], diff --git a/library.properties b/library.properties index edd6001..b7daa05 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=Trace -version=0.0.6 +version=1.0.0 author=Pavel Brychta maintainer=Pavel Brychta -sentence=Trace application internals & messages via web server -paragraph=Trace application internals & messages via web server +sentence=Trace application internals & messages via web server or other output device +paragraph=Trace application internals & messages via web server or other output device category=Other url=http://git.xpablo.cz/pablo2048/Trace architectures=* diff --git a/src/trace.cpp b/src/asyncWebsocket/traceAsyncWebsocket.cpp similarity index 63% rename from src/trace.cpp rename to src/asyncWebsocket/traceAsyncWebsocket.cpp index 0263eb7..19ffbdf 100644 --- a/src/trace.cpp +++ b/src/asyncWebsocket/traceAsyncWebsocket.cpp @@ -1,15 +1,15 @@ -#include "trace.h" -#include +#include "traceAsyncWebsocket.hpp" +#include #define MAX_TRACE_LINES 15 -#define MAX_LINE_LEN 50 +#define MAX_LINE_LEN 50 struct TraceLine { char _text[MAX_LINE_LEN + 1] = {0}; uint32_t _time{}; uint8_t _severity{}; - TraceLine(uint8_t severity, const char *str, uint16_t len) + TraceLine(uint8_t severity, const char * str, uint16_t len) { strncpy(_text, str, sizeof(_text)); _text[MAX_LINE_LEN] = 0; @@ -24,8 +24,7 @@ static TraceLine _lines[MAX_TRACE_LINES]; static uint16_t _lines_index = 0; static uint16_t _lines_count = 0; static volatile int _modified = 0; -static AsyncWebSocket *_wss = nullptr; // webovy soket pro trasovani -static Interval _tint(TRACE_CHECK_INTERVAL); // interval pro casovani stopare +static AsyncWebSocket * _wss = nullptr; // webovy soket pro trasovani static void (*message_cb)(const char *) = nullptr; @@ -36,7 +35,7 @@ static int modulo(int a, int b) return ((r < 0) ? r + b : r); } -static TraceLine &trace_line(uint16_t index) +static TraceLine & trace_line(uint16_t index) { int start = _lines_index - _lines_count; int idx = modulo(start + index, _lines_count); @@ -44,7 +43,7 @@ static TraceLine &trace_line(uint16_t index) return (_lines[idx]); } -static void print(uint8_t severity, const char *buffer, int length) +static void print(uint8_t severity, const char * buffer, int length) { char lin[MAX_LINE_LEN + 1]; unsigned int lineptr = 0; @@ -69,12 +68,39 @@ static void print(uint8_t severity, const char *buffer, int length) ++_modified; } +static void trace_loop() +{ + + if (nullptr != _wss) { + // je definovany webovy soket + if (_modified) { + // mame nejakou zmenu + if (_wss->count() != 0) { + // mame klienty + String log; + + _modified = 0; // rusime pozadavek na odeslani novych dat + if (log.reserve((MAX_TRACE_LINES * MAX_LINE_LEN) + (MAX_TRACE_LINES * 50))) { + log = F("{\"type\":\"trace\",\"data\":["); + trace_dumpJSON(log); + log.concat(F("]}")); + if (_wss->availableForWriteAll()) + _wss->textAll(log); + } else if (_wss->availableForWriteAll()) + _wss->textAll(F("{\"type\":\"trace\",\"text\":\"Memory error\"}")); + } else + _modified = 0; // zadny pripojeny klient - po pripojeni stejne musime vyzadat stav, takze ted muzeme modifikaci klidne ignorovat + } + } +} + void trace_init() { + Chronos::attachMs(TRACEWS_CHECK_INTERVAL, trace_loop); } -static String _getText(const char *buffer) +static String _getText(const char * buffer) { String res; @@ -82,43 +108,43 @@ static String _getText(const char *buffer) while (0 != *buffer) { switch (*buffer) { // uprava escape sekvenci pro JSON/HTML - case '"': - res.concat(F("\\\"")); - break; + case '"': + res.concat(F("\\\"")); + break; - case '\\': - res.concat(F("\\\\")); - break; + case '\\': + res.concat(F("\\\\")); + break; - case '/': - res.concat(F("\\/")); - break; + case '/': + res.concat(F("\\/")); + break; - case '<': - res.concat(F("<")); - break; + case '<': + res.concat(F("<")); + break; - case '>': - res.concat(F(">")); - break; + case '>': + res.concat(F(">")); + break; - default: - if (*buffer < 128) - res.concat(*buffer); - else { - char chr[3]; - res.concat(F("\\u00")); - sprintf_P(chr, PSTR("%02X"), *buffer); - res.concat(chr); - } - break; + default: + if (*buffer < 128) + res.concat(*buffer); + else { + char chr[3]; + res.concat(F("\\u00")); + sprintf_P(chr, PSTR("%02X"), *buffer); + res.concat(chr); + } + break; } ++buffer; } return res; } -void trace_dumpJSON(String &str) +void trace_dumpJSON(String & str) { for (int i = 0; i < _lines_count; i++) { @@ -150,20 +176,20 @@ void trace_end() trace_clear(); } -void trace_print(uint8_t severity, const __FlashStringHelper *fmt, ...) +void trace_print(uint8_t severity, const __FlashStringHelper * fmt, ...) { char buffer[MAX_LINE_LEN + 1]; va_list args; int length; va_start(args, fmt); - length = vsnprintf_P(buffer, sizeof (buffer), (const char *)fmt, args); + length = vsnprintf_P(buffer, sizeof(buffer), (const char *) fmt, args); va_end(args); print(severity, buffer, length); } -void trace_print(uint8_t severity, const char *fmt, ...) +void trace_print(uint8_t severity, const char * fmt, ...) { char buffer[MAX_LINE_LEN + 1]; va_list args; @@ -182,7 +208,7 @@ void trace_registermessagecb(void (*cb)(const char *)) message_cb = cb; } -void trace_addweb(AsyncWebSocket *socket) +void trace_addweb(AsyncWebSocket * socket) { _wss = socket; @@ -198,7 +224,7 @@ static char hexascii(uint8_t n) return n + '0'; } -void trace_dump(uint8_t severity, const char *prefix, uint8_t *address, size_t size) +void trace_dump(uint8_t severity, const char * prefix, uint8_t * address, size_t size) { char buffer[MAX_LINE_LEN + 1 + 3]; int idx = 0; @@ -220,7 +246,7 @@ void trace_dump(uint8_t severity, const char *prefix, uint8_t *address, size_t s print(severity, buffer, idx); } -void trace_dump(uint8_t severity, const __FlashStringHelper *prefix, uint8_t *address, size_t size) +void trace_dump(uint8_t severity, const __FlashStringHelper * prefix, uint8_t * address, size_t size) { char buffer[MAX_LINE_LEN + 1 + 3]; int idx = 0; @@ -228,7 +254,7 @@ void trace_dump(uint8_t severity, const __FlashStringHelper *prefix, uint8_t *ad if (prefix) { char dummy[64]; - strcpy_P(dummy, (const char *)prefix); + strcpy_P(dummy, (const char *) prefix); idx = snprintf_P(buffer, MAX_LINE_LEN, PSTR("%s"), dummy); } @@ -252,33 +278,4 @@ void trace_forceupdate(void) ++_modified; // vynutime odeslani informaci } -void trace_poll() -{ - - if (nullptr != _wss) { - // je definovany webovy soket - if (_modified) { - // mame nejakou zmenu - if (_wss->count() != 0) { - // mame klienty - if (_tint.expired()) { - // .. a vyprsel timeout pro obcerstvovani - String log; - - _modified = 0; // rusime pozadavek na odeslani novych dat - if (log.reserve((MAX_TRACE_LINES * MAX_LINE_LEN) + (MAX_TRACE_LINES * 50))) { - log = F("{\"type\":\"trace\",\"data\":["); - trace_dumpJSON(log); - log.concat(F("]}")); - if (_wss->availableForWriteAll()) - _wss->textAll(log); - } else - if (_wss->availableForWriteAll()) - _wss->textAll(F("{\"type\":\"trace\",\"text\":\"Memory error\"}")); - } - } else - _modified = 0; // zadny pripojeny klient - po pripojeni stejne musime vyzadat stav, takze ted muzeme modifikaci klidne ignorovat - } - } -} // EOF diff --git a/src/asyncWebsocket/traceAsyncWebsocket.hpp b/src/asyncWebsocket/traceAsyncWebsocket.hpp new file mode 100644 index 0000000..334146e --- /dev/null +++ b/src/asyncWebsocket/traceAsyncWebsocket.hpp @@ -0,0 +1,108 @@ +/** + * @file traceWebsocket.h + * @author Pavel Brychta, http://www.xpablo.cz + * + * Copyright (c) 2016-24 Pavel Brychta. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#pragma once + +#include +#include + +#define TRACEWS_CHECK_INTERVAL 200 // interval [ms], po kterem je testovano odesilani stopare + +/** + * @brief Inicializace modulu + */ +void trace_init(); + +/** + * @brief Ziskani vypisu v JSON formatu + * + * @param str retezec udalosti v JSON + */ +void trace_dumpJSON(String & str); + +/** + * @brief Vyprazdneni stopovaciho bufferu + */ +void trace_clear(); + +/** + * @brief Ukonceni prace stopare - vyprazdni buffer + */ +void trace_end(); + +/** + * @brief Ulozeni zpravy s obsahem z programove pameti (PROGMEM, F, ...) + * + * @param[in] severity Uroven - viz. TRACE_ERROR, TRACE_WARNING, ... + * @param[in] fmt Formatovaci retezec vysledne zpravy. Je ulozeny v PROGMEM + * @param[in] Parametry, ktere jsou dosazeny do formatovaciho retezce + */ +void trace_print(uint8_t severity, const __FlashStringHelper * fmt, ...); + +/** + * @brief Ulozeni zpravy + * + * @param[in] severity Uroven - viz. TRACE_ERROR, TRACE_WARNING, ... + * @param[in] fmt Formatovaci retezec vysledne zpravy. + * @param[in] Parametry, ktere jsou dosazeny do formatovaciho retezce + */ +void trace_print(uint8_t severity, const char * fmt, ...); + +/** + * @brief Registrace callback metody - je volana pri kazde zmene (zapisu) do stopare + * + * @param[in] Ukazatel na volanou metodu + */ +void trace_registermessagecb(void (*)(const char * msg)); + +/** + * @brief Pridani obsluhy stranky /trace do weboveho serveru + * + * @param socket webovy soket pro komunikaci + */ +void trace_addweb(AsyncWebSocket * socket); + +void trace_printfunc(uint8_t severity, const char * func, const char * file, int line, const char * fmt, ...); + +/** + * @brief Vypis oblasti pameti (dump) + * + * @param[in] severity Uroven - viz. TRACE_ERROR, TRACE_WARNING, ... + * @param[in] prefix Prefix (text), ktery je uvedeny pred vlastnim vypisem pameti + * @param address Adresa pocatku vypisu + * @param[in] size Pocet vypisovanych bytu (POZOR!!! musi se vejit do jednoho radku stopare!!!) + */ +void trace_dump(uint8_t severity, const char * prefix, uint8_t * address, size_t size); + +/** + * @brief Vypis oblasti pameti (dump) + * + * @param[in] severity Uroven - viz. TRACE_ERROR, TRACE_WARNING, ... + * @param[in] prefix Prefix (text), ktery je uvedeny pred vlastnim vypisem pameti + * @param address Adresa pocatku vypisu + * @param[in] size Pocet vypisovanych bytu (POZOR!!! musi se vejit do jednoho radku stopare!!!) + */ +void trace_dump(uint8_t severity, const __FlashStringHelper * prefix, uint8_t * address, size_t size); + +/** + * @brief Vynuceni odeslani obsahu bufferu (napr. pri obnovovani spojeni) + */ +void trace_forceupdate(); diff --git a/src/trace.h b/src/trace.h index 46a7634..d4a7b90 100644 --- a/src/trace.h +++ b/src/trace.h @@ -2,7 +2,7 @@ * @file trace.h * @author Pavel Brychta, http://www.xpablo.cz * - * Copyright (c) 2016-23 Pavel Brychta. All rights reserved. + * Copyright (c) 2016-24 Pavel Brychta. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,125 +22,81 @@ #pragma once // Definice jednotlivych typu hlaseni do trasovani -#define TRACE_ERROR 0 // chybova zprava = cervena -#define TRACE_WARNING 1 // varovani - zluta -#define TRACE_INFO 2 // informacni zprava - zelena -#define TRACE_DEBUG 3 // ladici zprava - cerna -#define TRACE_DEBUGMORE 4 // mene zajimava ladici zprava - take cerna - -#define TRACE_CHECK_INTERVAL 200 // interval [ms], po kterem je testovano odesilani stopare - -#ifndef DONT_USE_TRACE - -#include -#include - -/** - * @brief Inicializace modulu - */ -void trace_init(); - -/** - * @brief Ziskani vypisu v JSON formatu - * - * @param str retezec udalosti v JSON - */ -void trace_dumpJSON(String &str); - -/** - * @brief Vyprazdneni stopovaciho bufferu - */ -void trace_clear(); - -/** - * @brief Ukonceni prace stopare - vyprazdni buffer - */ -void trace_end(); - -/** - * @brief Ulozeni zpravy s obsahem z programove pameti (PROGMEM, F, ...) - * - * @param[in] severity Uroven - viz. TRACE_ERROR, TRACE_WARNING, ... - * @param[in] fmt Formatovaci retezec vysledne zpravy. Je ulozeny v PROGMEM - * @param[in] Parametry, ktere jsou dosazeny do formatovaciho retezce - */ -void trace_print(uint8_t severity, const __FlashStringHelper *fmt, ...); - -/** - * @brief Ulozeni zpravy - * - * @param[in] severity Uroven - viz. TRACE_ERROR, TRACE_WARNING, ... - * @param[in] fmt Formatovaci retezec vysledne zpravy. - * @param[in] Parametry, ktere jsou dosazeny do formatovaciho retezce - */ -void trace_print(uint8_t severity, const char *fmt, ...); - -/** - * @brief Registrace callback metody - je volana pri kazde zmene (zapisu) do stopare - * - * @param[in] Ukazatel na volanou metodu - */ -void trace_registermessagecb(void (*)(const char *msg)); - -/** - * @brief Pridani obsluhy stranky /trace do weboveho serveru - * - * @param socket webovy soket pro komunikaci - */ -void trace_addweb(AsyncWebSocket *socket); - -/** - * @brief Periodicky tik modulem - osetruje odeslani novych dat v pripade modifikace - */ -void trace_poll(); - -void trace_printfunc(uint8_t severity, const char *func, const char *file, int line, const char *fmt, ...); - -/** - * @brief Vypis oblasti pameti (dump) - * - * @param[in] severity Uroven - viz. TRACE_ERROR, TRACE_WARNING, ... - * @param[in] prefix Prefix (text), ktery je uvedeny pred vlastnim vypisem pameti - * @param address Adresa pocatku vypisu - * @param[in] size Pocet vypisovanych bytu (POZOR!!! musi se vejit do jednoho radku stopare!!!) - */ -void trace_dump(uint8_t severity, const char *prefix, uint8_t *address, size_t size); - -/** - * @brief Vypis oblasti pameti (dump) - * - * @param[in] severity Uroven - viz. TRACE_ERROR, TRACE_WARNING, ... - * @param[in] prefix Prefix (text), ktery je uvedeny pred vlastnim vypisem pameti - * @param address Adresa pocatku vypisu - * @param[in] size Pocet vypisovanych bytu (POZOR!!! musi se vejit do jednoho radku stopare!!!) - */ -void trace_dump(uint8_t severity, const __FlashStringHelper *prefix, uint8_t *address, size_t size); - -/** - * @brief Vynuceni odeslani obsahu bufferu (napr. pri obnovovani spojeni) - */ -void trace_forceupdate(); +#define TRACE_NONE -1 // nic +#define TRACE_ERROR 0 // chybova zprava = cervena +#define TRACE_WARNING 1 // varovani - zluta +#define TRACE_INFO 2 // informacni zprava - zelena +#define TRACE_DEBUG 3 // ladici zprava - cerna +#define TRACE_VERBOSE 4 // mene zajimava ladici zprava - take cerna +#ifndef TRACE_LIMIT + #define TRACE_LIMIT TRACE_DEBUG +#endif #define STRINGIFY(x) #x -#define TOSTRING(x) STRINGIFY(x) +#define TOSTRING(x) STRINGIFY(x) -#define TRACEPLUS(when, severity, ...) if (when != 0) TRACE(severity, __VA_ARGS__) -//#define TRACE(severity, ...) trace_print(severity, __VA_ARGS__) -#define TRACE(severity, text, ...) trace_print(severity, PSTR(text), ##__VA_ARGS__) -#define TRACEFUNC(severity, ...) trace_printfunc(severity, __func__, __FILE__, TOSTRING(__LINE__), __VA_ARGS__) -#define TRACEDUMP(severity, prefix, address, size) trace_dump(severity, prefix, address, size) -#define TRACE_INIT(a) trace_init() -#define TRACE_ADDWEB(srv) trace_addweb(srv) -#define TRACE_POLL(a) trace_poll() -#define TRACE_FORCEUPDATE(a) trace_forceupdate() +#if defined(TRACE_USE_ASYNC_WEBSOCKET) + #include "asyncWebsocket/traceAsyncWebsocket.hpp" + #define TRACEPLUS(when, severity, ...) \ + { \ + if (when > 0) \ + TRACE(severity, __VA_ARGS__) \ + } + #define TRACE(severity, text, ...) \ + { \ + constexpr bool trace_limit = (severity <= TRACE_LIMIT); \ + if (trace_limit) \ + trace_print(severity, PSTR(text), ##__VA_ARGS__); \ + } + #define TRACEFUNC(severity, ...) trace_printfunc(severity, __func__, __FILE__, TOSTRING(__LINE__), __VA_ARGS__) + #define TRACEDUMP(severity, prefix, address, size) trace_dump(severity, prefix, address, size) + #define TRACE_INIT(a) trace_init() + #define TRACE_ADDWEB(srv) trace_addweb(srv) + #define TRACE_FORCEUPDATE(a) trace_forceupdate() -#else // DONT_USE_TRACE -#define TRACEPLUS(...) ((void)0) -#define TRACE(...) ((void)0) // from assert.h "NOP" - http://stackoverflow.com/questions/9187628/c-empty-function-macros -#define TRACEFUNC(...) ((void)0) -#define TRACEDUMP(...) ((void)0) -#define TRACE_INIT(a) ((void)0) -#define TRACE_ADDWEB(a) ((void)0) -#define TRACE_POLL(a) ((void)0) -#define TRACE_FORCEUPDATE(a) ((void)0) -#endif // DONT_USE_TRACE +#else + #define TRACEPLUS(...) ((void) 0) + #if defined(ESP32) + #include + #define TRACE(severity, format, ...) \ + { \ + constexpr int s = severity; \ + if (s == TRACE_ERROR) \ + log_e(format, ##__VA_ARGS__); \ + else if (s == TRACE_DEBUG) \ + log_d(format, ##__VA_ARGS__); \ + else if (s == TRACE_WARNING) \ + log_w(format, ##__VA_ARGS__); \ + else if (s == TRACE_INFO) \ + log_i(format, ##__VA_ARGS__); \ + else if (s == TRACE_VERBOSE) \ + log_v(format, ##__VA_ARGS__); \ + } + #else + #ifdef DEBUG_ESP_PORT + #include + #define TRACE(severity, text, ...) \ + { \ + constexpr int s = severity; \ + if (s == TRACE_ERROR) \ + DEBUG_ESP_PORT.printf_P(PSTR("%8ld [E] " text "\n"), millis(), ##__VA_ARGS__); \ + else if (s == TRACE_DEBUG) \ + DEBUG_ESP_PORT.printf_P(PSTR("%8ld [D] " text "\n"), millis(), ##__VA_ARGS__); \ + else if (s == TRACE_WARNING) \ + DEBUG_ESP_PORT.printf_P(PSTR("%8ld [W] " text "\n"), millis(), ##__VA_ARGS__); \ + else if (s == TRACE_INFO) \ + DEBUG_ESP_PORT.printf_P(PSTR("%8ld [I] " text "\n"), millis(), ##__VA_ARGS__); \ + else if (s == TRACE_VERBOSE) \ + DEBUG_ESP_PORT.printf_P(PSTR("%8ld [V] " text "\n"), millis(), ##__VA_ARGS__); \ + } + #else + #warning TRACE output is disabled! + #define TRACE(...) ((void) 0) // from assert.h "NOP" - http://stackoverflow.com/questions/9187628/c-empty-function-macros + #endif + #endif + #define TRACEFUNC(...) ((void) 0) + #define TRACEDUMP(...) ((void) 0) + #define TRACE_INIT(a) ((void) 0) + #define TRACE_ADDWEB(a) ((void) 0) + #define TRACE_FORCEUPDATE(a) ((void) 0) +#endif