Logger library enables you to use unified interface to send out or receive data using one function with different parameters. You leave buffer overflows to this library as it handles it all.

Logger library howto guide.

Below is a simple program that outlines the usage of the logger library, The whole function was head-written so there might be some errors, but it is more for a live representation of usage than anything else. If someone would write a nice example program feel free to link it here.

simple usage of logger library

#include "mbed.h"
#include "logger.h"
#include "errno.h"

Ticker printout;
/**
 * \def STASH_BUFFER_LEN
 * size of stash buffer that can be used to store logged data
 */
#define STASH_BUFFER_LEN 70000
/// stash_buffer size
static char stash_buffer[STASH_BUFFER_LEN];

/**
 * Log_pop_periodic is periodically printing the messages until the buffer is empty. 
 * Once the buffer is empty it detaches and waits for another command.
*/
void log_pop_periodic(void)
{
    if( log_pop(L_BTSERIAL,stash_buffer,STASH_BUFFER_LEN) == 1 )
    {
        printout.detach();
    }
}

static int i=0;
static char read_buffer[20];
/**
 * read data from BT serial
*/
void read_from_BT()
{

    if (BTSerial.readable()) {
        read_buffer[i++] = BTSerial.getc();
        // if we read the desired character
        if (read_buffer[i-1] == 'p')
        {
            // start the printout process which will log_pop logged data
            printout.attach(&log_pop_periodic,0.5);
        }
    }    
}

int main()
{
    log_init(L_SERIAL);
    log_init(L_BTSERIAL);
    BTSerial.attach(&read_from_BT);

    // while loop to fill in loads of stinky data
    while (1) {
            // read something, then stash it
            log_stash(L_INFO,print_buffer,strlen(print_buffer),stash_buffer,STASH_BUFFER_LEN);
    }
}

logger.cpp

Committer:
Letme
Date:
2014-09-08
Revision:
2:9d04753a3ad2
Parent:
1:8837abc3f763
Child:
3:e1ed8ae7691e

File content as of revision 2:9d04753a3ad2:

#include "mbed.h"
#include "logger.h"
#include "errno.h"

/**
 * @defgroup logger_lib Logger library
 * @{
 * @author Crt Lukancic Mori (crt@tech-review.net)
 * @short Logging library provides more standard re-routing of output.
 * @details While data logger needs an input to define where it output should go, we
 * could also override the output using a global variable, which would be read
 * before the entry into plc switch to override the local output request.
 *
 */ 

//Serial logSerial(PA_2, PA_3);
Serial logSerial(PA_9, PA_10);
char endline[]="\r\n";

/**
 * Log_init initializes place where messages will be storred
 * @param plc Place id to initialize
 *
 * @retval 1 when succcess
 * @retval -ERR linux errno.h error message
 */
int32_t log_init(uint8_t plc) {
    switch(plc) {
        case L_SERIAL:
            /// initialize baudrate
            logSerial.baud(115700);
            logSerial.printf("Serial port initialized\r\n");
            break;
        case L_FILE:
            break;
        case L_LED:
            // find out what we want here -morse code would be fun ;)
            break;
        default:
            return -EINVAL;
    }

    return 1;
}

/**
 * Log_msg determines where to save message.
 * @param plc Place id, where to store message(check logger.h for more infos)
 * @param lvl Debug level (ERROR,WARNING,DEBUG)
 * @param msg pointer to message
 * @param length length of message
 *
 * @retval 1 when succcess
 * @retval -ERR linux errno error message
 */
int32_t log_msg(uint8_t plc, uint8_t lvl, char *msg, uint32_t length) {
    char send_message[length+5]; // add as much as you need to get all chars in (dont forget the \n on end)

    switch(lvl) {
        case L_CRIT_ERROR:
            snprintf(send_message,length+7,"CE: %s %s",msg,endline);
            break;
        case L_ERROR:
            snprintf(send_message,length+6,"E: %s %s",msg,endline);
            break;
        case L_WARNING:
            snprintf(send_message,length+6,"W: %s %s",msg,endline);
            break;
        case L_DEBUG:
            snprintf(send_message,length+6,"D: %s %s",msg,endline);
            break;
        case L_INFO:
            snprintf(send_message,length+6,"I: %s %s",msg,endline);
            break;
        default:
            return -EINVAL;
    }

    switch(plc) {
        case L_SERIAL:
            if(logSerial.writeable()) {
                logSerial.printf(send_message);
            } else {
                return -EBUSY;
            }
            break;
        case L_FILE:
            break;
        case L_LED:
            // find out what we want here -morse code would be fun ;)
            break;
        default:
            return -EINVAL;

    }

    return 1;
}

/// stash_buffer size
char stash_buffer[STASH_BUFFER_LEN];
/**
 * Log_stash is meant to stash logs until they are ready to be sent, using log_pop function
 * Remember that this function can return also buffer full as result, which means you have to keep
 * deciding what you want to do - it just stashes files, but it keeps them in in case of buffer overflow.
 * @param lvl Debug level (ERROR,WARNING,DEBUG)
 * @param msg pointer to message
 * @param length length of message
 *
 * @retval 1 success
 * @retval -ERR linux errno error message - also includes buffer full!
 *
 * @warning STASH_BUFFER_LEN sets the size of stash buffer - in case you are lacking space consider making the buffer smaller
 */
int32_t log_stash(uint8_t lvl, char *msg, uint32_t length) {
    char stash_buffer_tmp[length+8];
    // check if buffer is full and set starting point
    if(strlen(stash_buffer)>STASH_BUFFER_LEN) {
        return -EFBIG;
    }

    // now fill it
    switch(lvl) {
        case L_CRIT_ERROR:
            snprintf(stash_buffer_tmp,length+7,"CE: %s %s",msg,endline);
            break;
        case L_ERROR:
            snprintf(stash_buffer_tmp,length+6,"E: %s %s",msg,endline);
            break;
        case L_WARNING:
            snprintf(stash_buffer_tmp,length+6,"W: %s %s",msg,endline);
            break;
        case L_DEBUG:
            snprintf(stash_buffer_tmp,length+6,"D: %s %s",msg,endline);
            break;
        case L_INFO:
            snprintf(stash_buffer_tmp,length+6,"I: %s %s",msg,endline);
            break;
        default:
            return -EINVAL;
    }
    strcat(stash_buffer,stash_buffer_tmp);
    return 1;
}

/**
 * Log_pop function sends everything log_stash stashed
 * @param plc Place to where you pop stashed messages
 *
 * @retval 1 for sucess
 * @retval -ERR errno.h error message
 */
int32_t log_pop(uint8_t plc) {
    switch(plc) {
        case L_SERIAL:
            if(logSerial.writeable()) {
                logSerial.printf(stash_buffer);
            } else {
                return -EBUSY;
            }
            break;
        case L_FILE:
            break;
        case L_LED:
            // find out what we want here -morse code would be fun ;)
            break;
        default:
            return -EINVAL;

    }
    
    //clear stash buffer
    int i;
    for(i=0;i<STASH_BUFFER_LEN;++i) {
        stash_buffer[i]=0;    
    }
    return 1;
}
/**
 * @}
 */