Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/BridgeLogger.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include "BridgeLogger.h"

#ifndef CUSTOM_BRIDGE_LOG
#include "DebugLogger.h"

namespace mesh {

// The default logger for bridge logging is just the debug logger.
Logger& bridgeLog = debugLog;

} // namespace mesh

#endif
14 changes: 14 additions & 0 deletions src/BridgeLogger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#include "Logger.h"

namespace mesh {

/// @brief The global logging instance meant for logs from bridge implementations
///
/// By default this is set to debugLog, but can be overriden by defining
/// CUSTOM_BRIDGE_LOG in a build configuration and then providing an
/// alternative global definition (eg. `Logger& bridgeLog = myCustomLogger;`)
extern Logger& bridgeLog;

} // namespace mesh
81 changes: 81 additions & 0 deletions src/DebugLogger.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#include "DebugLogger.h"

#ifndef CUSTOM_DEBUG_LOG
#include <Arduino.h>
#include <Utils.h>

namespace mesh {

class DefaultDebugLogger : public Logger {
public:
DefaultDebugLogger() {}

size_t write(uint8_t b) override { return Serial.write(b); }

size_t write(const uint8_t *buffer, size_t size) override { return Serial.write(buffer, size); }

size_t printf(const char *format, ...) override __attribute__((format(printf, 2, 3))) {
va_list args;
va_start(args, format);
size_t written = vprintf(format, args);
va_end(args);
return written;
}

size_t print(char c) override { return Serial.print(c); }

size_t print(const char str[]) override { return Serial.print(str); }

size_t printlnf(const char *format, ...) override __attribute__((format(printf, 2, 3))) {
va_list args;
va_start(args, format);
size_t written = vprintf(format, args);
va_end(args);
written += Serial.println();
return written;
}

size_t println(void) override { return Serial.println(); }

size_t println(char c) override { return Serial.println(c); }

size_t println(const char str[]) override { return Serial.println(str); }

void printHex(const uint8_t* src, size_t len) override {
mesh::Utils::printHex(Serial, src, len);
}

void flush() override { Serial.flush(); }

private:
size_t vprintf(const char* format, va_list arg) {
char loc_buf[64];
char *temp = loc_buf;
va_list copy;
va_copy(copy, arg);
int len = vsnprintf(temp, sizeof(loc_buf), format, copy);
va_end(copy);
if (len < 0) {
return 0;
}
if (len >= (int)sizeof(loc_buf)) { // comparation of same sign type for the compiler
temp = (char *)malloc(len + 1);
if (temp == NULL) {
return 0;
}
len = vsnprintf(temp, len + 1, format, arg);
}
len = write((uint8_t *)temp, len);
if (temp != loc_buf) {
free(temp);
}
return len;
}
};

DefaultDebugLogger defaultDebugLogger;
Logger& debugLog = defaultDebugLogger;

} // namespace mesh

#endif
16 changes: 16 additions & 0 deletions src/DebugLogger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include "Logger.h"

namespace mesh {

/// @brief The global logging instance meant for debug logs
///
/// By default this is set to an implementation which forwards to the
/// equivalent methods in the Arduino core `Serial` instance. This can be
/// overridden by defining CUSTOM_DEBUG_LOG in a build configuration and then
/// providing an alternative global definition. For example:
/// `Logger& debugLog = myCustomLogger;`.
extern Logger& debugLog;

} // namespace mesh
97 changes: 97 additions & 0 deletions src/Logger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#pragma once

#include <cstddef>
#include <cstdint>

namespace mesh {

/// @brief An abstraction for text based logging in MeshCore
class Logger {
public:
virtual ~Logger() = default;

/// @brief Writes a single byte to the log
///
/// @param b An unsigned byte to be written to the log.
/// @return The number of bytes written to the log (always one).
virtual size_t write(uint8_t b) = 0;

/// @brief Writes the specified number of bytes to the log
///
/// @param buffer A pointer to an array of bytes to be written to the log.
/// @param size The number of bytes in the array to be written to the log.
/// @return The number of bytes written to the log.
virtual size_t write(const uint8_t *buffer, size_t size) = 0;

/// @brief Formats a string and writes it to the log
///
/// @param format A format string used to generate what will be written to
/// the log.
/// @param args Any values required by the format string.
/// @return The number of bytes written to the log.
virtual size_t printf(const char * format, ...)
__attribute__ ((format (printf, 2, 3))) = 0;

/// @brief Writes a single character to the log
///
/// @param c A character to be written to the log.
/// @return The number of bytes written to the log (always one).
virtual size_t print(char c) = 0;

/// @brief Writes a null-terminated string to the log
///
/// NOTE: The null terminator is not written to the log.
///
/// @param str A pointer to a null-terminated string to be written to the
/// log.
/// @return The number of bytes written to the log.
virtual size_t print(const char str[]) = 0;

/// @brief Formats a string and writes it to the log followed by a newline
///
/// NOTE: The type of newline (eg. LF vs. CRLF) is implementation dependent.
///
/// @param format A format string used to generate what will be written to
/// the log.
/// @param args Any values required by the format string.
/// @return The number of bytes written to the log.
virtual size_t printlnf(const char * format, ...)
__attribute__ ((format (printf, 2, 3))) = 0;

/// @brief Writes a newline to the log.
///
/// NOTE: The type of newline (eg. LF vs. CRLF) is implementation dependent.
///
/// @return The number of bytes written to the log.
virtual size_t println(void) = 0;

/// @brief Writes a single character to the log follwed by a newline
///
/// NOTE: The type of newline (eg. LF vs. CRLF) is implementation dependent.
///
/// @param c A character to be written to the log.
/// @return The number of bytes written to the log.
virtual size_t println(char c) = 0;

/// @brief Writes a null-terminated string to the log followed by a newline
///
/// NOTE: The null terminator is not written to the log.
/// NOTE: The type of newline (eg. LF vs. CRLF) is implementation dependent.
///
/// @param str A pointer to a null-terminated string to be written to the
/// log.
/// @return The number of bytes written to the log.
virtual size_t println(const char str[]) = 0;

/// @brief Write a byte array to the log in ASCII hex format.
///
/// @param src An array of bytes to convert to ASCII hex format and then
/// write to the log.
/// @param len The number of bytes in the array to convert and write.
virtual void printHex(const uint8_t* src, size_t len) = 0;

/// @brief Flush any data buffered by the Logger implementation
virtual void flush() = 0;
};

} // namespace mesh
13 changes: 13 additions & 0 deletions src/PacketLogger.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include "PacketLogger.h"

#ifndef CUSTOM_PACKET_LOG
#include <DebugLogger.h>

namespace mesh {

// The default logger for packet logging is just the debug logger.
Logger& packetLog = debugLog;

} // namespace mesh

#endif
14 changes: 14 additions & 0 deletions src/PacketLogger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#include "Logger.h"

namespace mesh {

/// @brief The global logging instance meant for packet logging
///
/// By default this is set to debugLog, but can be overriden by defining
/// CUSTOM_PACKET_LOG in a build configuration and then providing an
/// alternative global definition (eg. `Logger& packetLog = myCustomLogger;`)
extern Logger& packetLog;

} // namespace mesh