INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.

Antwort schreiben 
 
Themabewertung:
  • 0 Bewertungen - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Logging nach Serial und/oder Telnet
28.12.2020, 19:23
Beitrag #1
Logging nach Serial und/oder Telnet
Wird mal wieder ein bisschen kompliziert, fürchte ich... Wink

Ich habe eine Log- und Tracelibrary, die mit Präprozessormakros arbeitet und so nur die Log-Ausgaben im Compilat lässt, die über einem gewählten Loglevel liegen.
Man benutzt Statements wie dieses:
Code:
LOG_E("Das ist eine Testausgabe um %lu\n", millis());
Die werden dann ein paar mal expandiert und enden in sowas:
Code:
LOGDEVICE.printf("[E] %lu| %-20s [%4d] %s: Das ist eine Testausgabe um %lu\n", millis(), file_name(__FILE__), __LINE__, __func__, millis());

LOGDEVICE ist eine globale Variable vom Typ "Print&", also eine Referenz auf ein Print-Objekt, und wird mit
Code:
Print& LOGDEVICE = Serial;
initialisiert.

So weit, so gut und funktionierend.

Jetzt bin ich aktuell auf einem ESP8285 in einer Funksteckdose unterwegs, bei dem alle GPIOs belegt sind, so dass keine Serial verfügbar ist (ich käme auch nur schwer dran, ich habe ungern 230V offen liegen...).

Deswegen habe ich einen Telnetserver eingebaut, der alle angemeldeten Clients mit der gleichen Ausgabe beglückt. Das klappt ebenfalls wie gewünscht. Dieser Telnetserver erbt von Print und implementiert alle Funktionen bis auf
Code:
size_t write(uint8_t char);
als Template - die eine ist ja virtuell und muss implementiert werden. Das Template für print sieht dann so aus:
Code:
// Wrapper for all print() variants in Print
  template <typename... Args>
  size_t print(Args&&... args) { // NOLINT
    size_t len = 0;
    // Loop over clients
    for (uint8_t i = 0; i < TL_maxClients; ++i) {
      // Is it active?
      if (TL_Client[i] || TL_Client[i].connected()) {
        // Yes. print out line
        len = TL_Client[i].print(std::forward<Args>(args) ...);
      }
    }
    return len;
  }
Sie kopiert die Ausgabezeile an alle Clients, die momentan mit dem Server verbunden sind.

Die betreffende Klassendefinition ist
Code:
class TelnetLog : public Print {
...
};
- sie erbt also von Print. Das klappt auch prächtig, alle über TelnetLog abgesetzten print(), printf() usw. landen auf allen angeschlossenen Clients.

Jetzt zu meinem Problem: ich setze
Code:
LOGDEVICE = tl;
, was wegen der Vererbung von Print natürlich geht. Aber
  • Code:
    tl.print("bla");
    funktioniert.
  • Code:
    LOGDEVICE.print("bla");
    hingegen funktioniert nicht.

Mir ist nicht klar, warum. Wenn die Templatefunktion nicht anwendbar wäre, würde ich entweder einen Compilerfehler erwarten - der kommt nicht - oder, dass dann die entsprechende Funktion von Print benutzt würde - aber wie? Es gibt ja nur das TelnetLog-Objekt, auf das LOGDEVICE verweist. Und das hat ja eben ein Template für die print-Funktion.

Habt Ihr eine Idee?

Ich habe die Log- und Telnetserver-Sourcen mal angefügt.


Angehängte Datei(en)
.h  Logging.h (Größe: 6,32 KB / Downloads: 11)
.cpp  Logging.cpp (Größe: 1,7 KB / Downloads: 8)
.h  TelnetLog.h (Größe: 2,58 KB / Downloads: 7)
.cpp  TelnetLog.cpp (Größe: 2,62 KB / Downloads: 6)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
28.12.2020, 19:38
Beitrag #2
RE: Logging nach Serial und/oder Telnet
Nach meinem Verständnis braucht die von Print abgeletete Klasse eigentlich nur die write-Methode zu überschreiben. Die Unterstützung für die einzelnen Typen bringt schon Print mit.

Ich habe sowas Ähnliches mal gemacht. Ungetestet bezieht sich auf den ESP32, weil ich keinen hatte. Evtl. hilft es Dir.

Gruß Tommy

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
28.12.2020, 20:13
Beitrag #3
RE: Logging nach Serial und/oder Telnet
(28.12.2020 19:38)Tommy56 schrieb:  Nach meinem Verständnis braucht die von Print abgeletete Klasse eigentlich nur die write-Methode zu überschreiben. Die Unterstützung für die einzelnen Typen bringt schon Print mit.

Ich habe sowas Ähnliches mal gemacht. Ungetestet bezieht sich auf den ESP32, weil ich keinen hatte. Evtl. hilft es Dir.

Gruß Tommy

Ja, Deinen Telnetserver habe ich auch schon zu Rate gezogen Big Grin

Der ist aber nicht mein Problem. Mit dem Überladen von nur dem einzelnen write() könnte ich es mal probieren - das ist aber auch schon so geschrieben, dass es funktionieren sollte. Wenn die Templatefunktion nicht evaluiert werden kann, könnte es sein, dass der Compiler gar nichts erzeugt und dadurch der Funktionsaufruf einfach unterbleibt. Es gibt ja die SFINAE-Regel, aber ich hätte noch nicht erlebt, dass da dann überhaupt nichts passiert.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
28.12.2020, 20:23
Beitrag #4
RE: Logging nach Serial und/oder Telnet
Ich mag solche #define-Orgien nicht.

Da kann man doch ordentlich eine Klasse/Funktion bauen, die ein Print-Objekt als Referenz übernimmt und dann alle Funktionen hat. Das Debuglevel kann man ja über ein static enum bereit stellen.

Gruß Tommy

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
28.12.2020, 21:02
Beitrag #5
RE: Logging nach Serial und/oder Telnet
Das funktioniert nicht. Damit kannst Du die 1:n-Beziehung zu mehreren Telnetclients nicht ohne Klimmzüge abbilden. Das sind ja unbestimmt viele Print-Objekte. Und außerdem bekommst du ein größeres Binary dadurch.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
28.12.2020, 21:24 (Dieser Beitrag wurde zuletzt bearbeitet: 28.12.2020 21:43 von Tommy56.)
Beitrag #6
RE: Logging nach Serial und/oder Telnet
Mal real gedacht: Wozu brauchst Du zum Debuggen mehrere parallele Telnetsessions?
Nach meiner Meinung: Nie (oder willst Du stereo lesen?)

Das Problem ist also in der Praxis unsinnig. Es wird immer der letzte angemeldete Client bedient.

Gruß Tommy

Edit: Deine #define-Sammlung kann übrigens auch nur einen Client gleichzeitig bedienen. In dem Sinne ist Dein Titel irreführend. Das und muss weg.

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
28.12.2020, 22:19
Beitrag #7
RE: Logging nach Serial und/oder Telnet
(28.12.2020 19:23)miq19 schrieb:  Wird mal wieder ein bisschen kompliziert, fürchte ich... Wink
Das erscheint mir mehr als sehr komplex, wozu braucht man das eigentlich?

Gruß Fips

Meine Esp8266 & ESP32 Projekte
Webseite des Benutzers besuchen Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
28.12.2020, 22:33 (Dieser Beitrag wurde zuletzt bearbeitet: 28.12.2020 22:39 von Tommy56.)
Beitrag #8
RE: Logging nach Serial und/oder Telnet
Naja, loggen nach Serial oder Telnet mit Loglevels ohne den Code wesentlich zu ändern ist schon ganz brauchbar, besonders wenn das Teil im Einsatz da ist, wo du kein serielles Kabel ran bekommst. Man sollte die angezeigten Loglevels aber schon in dem Debugkanal interaktiv wählen können. Also eher von Stream ableiten, als von Print.

Gruß Tommy

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
Antwort schreiben 


Möglicherweise verwandte Themen...
Thema: Verfasser Antworten: Ansichten: Letzter Beitrag
  ESP8266 Webserver nach Zeit nicht mehr verfügbar. ESPWolf 19 660 17.01.2021 11:13
Letzter Beitrag: hotsystems
  falsches Display oder einfach nur keine Ahnung? Steinspiel 30 1.001 11.01.2021 19:48
Letzter Beitrag: Tommy56
  Erfahrungen mit ESP32 und WLAN/MQTT oder was ich beobachtet habe... Arduino4Fun 13 942 10.01.2021 14:18
Letzter Beitrag: nbk83
  ESP-32 USB->Serial Adapter Positiv 1 727 31.08.2020 19:04
Letzter Beitrag: KlaRa
  Esp8266 GPIO default In- oder Out-put? N1d45 0 663 29.08.2020 06:58
Letzter Beitrag: N1d45
  Grundsätzliche Fragen nach Umstieg von Lua auf Arduino Stefan72 6 1.294 06.07.2020 22:58
Letzter Beitrag: Stefan72
  WEMOS D1 mini pro nach 4 Jahren gestorben Tommy56 1 904 02.07.2020 05:52
Letzter Beitrag: amithlon
  Allgemeine Frage zu serial.Print array Benny86 4 1.156 16.06.2020 02:10
Letzter Beitrag: Benny86
  i2c LCD Display am Wemos D1 Mini mit mqtt klappt nach modifikation nicht raspido 5 1.351 15.06.2020 22:19
Letzter Beitrag: stw
  AI Thinker ESP32 CAM, Flash LED leuchtet leicht nach DEEP SLEEP spok1 0 887 01.06.2020 14:00
Letzter Beitrag: spok1

Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste