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);
    }
}
Committer:
Letme
Date:
Wed Dec 31 22:23:19 2014 +0000
Revision:
5:f232b826e1f2
Parent:
4:9360fdf3a818
Fixed some minor bugz and added clearing of stash buffer once whole chunk is printed to L_SERIAL. Also expanded documentation a bit.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Letme 0:272c70e2366c 1 #include "mbed.h"
Letme 0:272c70e2366c 2 #include "logger.h"
Letme 0:272c70e2366c 3 #include "errno.h"
Letme 0:272c70e2366c 4
Letme 2:9d04753a3ad2 5 /**
Letme 2:9d04753a3ad2 6 * @defgroup logger_lib Logger library
Letme 2:9d04753a3ad2 7 * @{
Letme 3:e1ed8ae7691e 8 * @author Crt Lukancic Mori (crt@tech-review.net or crt@the-mori.com)
Letme 2:9d04753a3ad2 9 * @short Logging library provides more standard re-routing of output.
Letme 2:9d04753a3ad2 10 * @details While data logger needs an input to define where it output should go, we
Letme 2:9d04753a3ad2 11 * could also override the output using a global variable, which would be read
Letme 5:f232b826e1f2 12 * before the entry into plc switch to override the local output request. Function
Letme 5:f232b826e1f2 13 * needs outside buffer definition on which it can stash messages and perform
Letme 5:f232b826e1f2 14 * a string buffer. This are then passed into stash and pop functions when
Letme 5:f232b826e1f2 15 * such logging is assummed.
Letme 2:9d04753a3ad2 16 *
Letme 2:9d04753a3ad2 17 */
Letme 0:272c70e2366c 18
Letme 3:e1ed8ae7691e 19 Serial logSerial(PA_2, PA_3);
Letme 3:e1ed8ae7691e 20 Serial BTSerial(PB_6, PA_10);
Letme 3:e1ed8ae7691e 21 char endline[]="\n";
Letme 1:8837abc3f763 22
Letme 0:272c70e2366c 23 /**
Letme 0:272c70e2366c 24 * Log_init initializes place where messages will be storred
Letme 3:e1ed8ae7691e 25 * @param[in] plc Place id to initialize
Letme 0:272c70e2366c 26 *
Letme 0:272c70e2366c 27 * @retval 1 when succcess
Letme 1:8837abc3f763 28 * @retval -ERR linux errno.h error message
Letme 0:272c70e2366c 29 */
Letme 1:8837abc3f763 30 int32_t log_init(uint8_t plc) {
Letme 0:272c70e2366c 31 switch(plc) {
Letme 0:272c70e2366c 32 case L_SERIAL:
Letme 1:8837abc3f763 33 /// initialize baudrate
Letme 1:8837abc3f763 34 logSerial.baud(115700);
Letme 1:8837abc3f763 35 logSerial.printf("Serial port initialized\r\n");
Letme 0:272c70e2366c 36 break;
Letme 0:272c70e2366c 37 case L_FILE:
Letme 0:272c70e2366c 38 break;
Letme 0:272c70e2366c 39 case L_LED:
Letme 0:272c70e2366c 40 // find out what we want here -morse code would be fun ;)
Letme 0:272c70e2366c 41 break;
Letme 3:e1ed8ae7691e 42 case L_BTSERIAL:
Letme 3:e1ed8ae7691e 43 logSerial.printf("BlueTooth initializing\r\n");
Letme 3:e1ed8ae7691e 44 BTSerial.baud(9600);
Letme 3:e1ed8ae7691e 45 logSerial.printf("OK\r\n");
Letme 3:e1ed8ae7691e 46 logSerial.printf("Serial port initialized\r\n");
Letme 3:e1ed8ae7691e 47 break;
Letme 0:272c70e2366c 48 default:
Letme 0:272c70e2366c 49 return -EINVAL;
Letme 0:272c70e2366c 50 }
Letme 0:272c70e2366c 51
Letme 0:272c70e2366c 52 return 1;
Letme 0:272c70e2366c 53 }
Letme 0:272c70e2366c 54
Letme 0:272c70e2366c 55 /**
Letme 0:272c70e2366c 56 * Log_msg determines where to save message.
Letme 3:e1ed8ae7691e 57 * @param[in] plc Place id, where to store message(check logger.h for more infos)
Letme 3:e1ed8ae7691e 58 * @param[in] lvl Debug level (ERROR,WARNING,DEBUG)
Letme 3:e1ed8ae7691e 59 * @param[in] msg pointer to message
Letme 3:e1ed8ae7691e 60 * @param[in] length length of message
Letme 0:272c70e2366c 61 *
Letme 0:272c70e2366c 62 * @retval 1 when succcess
Letme 0:272c70e2366c 63 * @retval -ERR linux errno error message
Letme 0:272c70e2366c 64 */
Letme 1:8837abc3f763 65 int32_t log_msg(uint8_t plc, uint8_t lvl, char *msg, uint32_t length) {
Letme 4:9360fdf3a818 66 if((msg == NULL) || (length == 0))
Letme 4:9360fdf3a818 67 {
Letme 4:9360fdf3a818 68 return -EINVAL;
Letme 4:9360fdf3a818 69 }
Letme 4:9360fdf3a818 70
Letme 0:272c70e2366c 71 char send_message[length+5]; // add as much as you need to get all chars in (dont forget the \n on end)
Letme 0:272c70e2366c 72
Letme 0:272c70e2366c 73 switch(lvl) {
Letme 0:272c70e2366c 74 case L_CRIT_ERROR:
Letme 1:8837abc3f763 75 snprintf(send_message,length+7,"CE: %s %s",msg,endline);
Letme 0:272c70e2366c 76 break;
Letme 0:272c70e2366c 77 case L_ERROR:
Letme 1:8837abc3f763 78 snprintf(send_message,length+6,"E: %s %s",msg,endline);
Letme 0:272c70e2366c 79 break;
Letme 0:272c70e2366c 80 case L_WARNING:
Letme 1:8837abc3f763 81 snprintf(send_message,length+6,"W: %s %s",msg,endline);
Letme 0:272c70e2366c 82 break;
Letme 0:272c70e2366c 83 case L_DEBUG:
Letme 1:8837abc3f763 84 snprintf(send_message,length+6,"D: %s %s",msg,endline);
Letme 0:272c70e2366c 85 break;
Letme 0:272c70e2366c 86 case L_INFO:
Letme 3:e1ed8ae7691e 87 snprintf(send_message,length+3,"%s %s",msg,endline);
Letme 0:272c70e2366c 88 break;
Letme 0:272c70e2366c 89 default:
Letme 0:272c70e2366c 90 return -EINVAL;
Letme 0:272c70e2366c 91 }
Letme 0:272c70e2366c 92
Letme 0:272c70e2366c 93 switch(plc) {
Letme 0:272c70e2366c 94 case L_SERIAL:
Letme 1:8837abc3f763 95 if(logSerial.writeable()) {
Letme 1:8837abc3f763 96 logSerial.printf(send_message);
Letme 1:8837abc3f763 97 } else {
Letme 1:8837abc3f763 98 return -EBUSY;
Letme 1:8837abc3f763 99 }
Letme 0:272c70e2366c 100 break;
Letme 0:272c70e2366c 101 case L_FILE:
Letme 0:272c70e2366c 102 break;
Letme 0:272c70e2366c 103 case L_LED:
Letme 0:272c70e2366c 104 // find out what we want here -morse code would be fun ;)
Letme 0:272c70e2366c 105 break;
Letme 3:e1ed8ae7691e 106 case L_BTSERIAL:
Letme 3:e1ed8ae7691e 107 if(BTSerial.writeable()) {
Letme 3:e1ed8ae7691e 108 BTSerial.printf(send_message);
Letme 3:e1ed8ae7691e 109 } else {
Letme 3:e1ed8ae7691e 110 return -EBUSY;
Letme 3:e1ed8ae7691e 111 }
Letme 3:e1ed8ae7691e 112 break;
Letme 0:272c70e2366c 113 default:
Letme 0:272c70e2366c 114 return -EINVAL;
Letme 0:272c70e2366c 115
Letme 0:272c70e2366c 116 }
Letme 0:272c70e2366c 117
Letme 0:272c70e2366c 118 return 1;
Letme 0:272c70e2366c 119 }
Letme 0:272c70e2366c 120
Letme 0:272c70e2366c 121 /**
Letme 0:272c70e2366c 122 * Log_stash is meant to stash logs until they are ready to be sent, using log_pop function
Letme 0:272c70e2366c 123 * Remember that this function can return also buffer full as result, which means you have to keep
Letme 0:272c70e2366c 124 * deciding what you want to do - it just stashes files, but it keeps them in in case of buffer overflow.
Letme 5:f232b826e1f2 125 * Stash buffer is defined outside library and passed in as memoryspace.
Letme 5:f232b826e1f2 126 *
Letme 3:e1ed8ae7691e 127 * @param[in] lvl Debug level (ERROR,WARNING,DEBUG)
Letme 3:e1ed8ae7691e 128 * @param[in] msg pointer to message
Letme 3:e1ed8ae7691e 129 * @param[in] length length of message
Letme 4:9360fdf3a818 130 * @param[in] *stash_buffer Place where stashed messages were saved
Letme 4:9360fdf3a818 131 * @param[in] stash_buffer_len how many characters can be saved on stashed message buffer
Letme 0:272c70e2366c 132 *
Letme 0:272c70e2366c 133 * @retval 1 success
Letme 0:272c70e2366c 134 * @retval -ERR linux errno error message - also includes buffer full!
Letme 0:272c70e2366c 135 *
Letme 0:272c70e2366c 136 */
Letme 4:9360fdf3a818 137 int32_t log_stash(uint8_t lvl, char *msg, uint32_t length, char *stash_buffer,size_t stash_buffer_len) {
Letme 4:9360fdf3a818 138 if((msg == NULL) || (length == 0) || (stash_buffer == NULL) || (stash_buffer_len == 0))
Letme 4:9360fdf3a818 139 {
Letme 4:9360fdf3a818 140 return -EINVAL;
Letme 4:9360fdf3a818 141 }
Letme 4:9360fdf3a818 142
Letme 1:8837abc3f763 143 char stash_buffer_tmp[length+8];
Letme 4:9360fdf3a818 144
Letme 0:272c70e2366c 145 // check if buffer is full and set starting point
Letme 4:9360fdf3a818 146 if((strlen(stash_buffer) > (stash_buffer_len-5)) || (stash_buffer_len < length)) {
Letme 1:8837abc3f763 147 return -EFBIG;
Letme 1:8837abc3f763 148 }
Letme 0:272c70e2366c 149
Letme 0:272c70e2366c 150 // now fill it
Letme 0:272c70e2366c 151 switch(lvl) {
Letme 0:272c70e2366c 152 case L_CRIT_ERROR:
Letme 1:8837abc3f763 153 snprintf(stash_buffer_tmp,length+7,"CE: %s %s",msg,endline);
Letme 0:272c70e2366c 154 break;
Letme 0:272c70e2366c 155 case L_ERROR:
Letme 1:8837abc3f763 156 snprintf(stash_buffer_tmp,length+6,"E: %s %s",msg,endline);
Letme 0:272c70e2366c 157 break;
Letme 0:272c70e2366c 158 case L_WARNING:
Letme 1:8837abc3f763 159 snprintf(stash_buffer_tmp,length+6,"W: %s %s",msg,endline);
Letme 0:272c70e2366c 160 break;
Letme 0:272c70e2366c 161 case L_DEBUG:
Letme 1:8837abc3f763 162 snprintf(stash_buffer_tmp,length+6,"D: %s %s",msg,endline);
Letme 0:272c70e2366c 163 break;
Letme 0:272c70e2366c 164 case L_INFO:
Letme 3:e1ed8ae7691e 165 snprintf(stash_buffer_tmp,length+3,"%s %s",msg,endline);
Letme 0:272c70e2366c 166 break;
Letme 0:272c70e2366c 167 default:
Letme 0:272c70e2366c 168 return -EINVAL;
Letme 0:272c70e2366c 169 }
Letme 1:8837abc3f763 170 strcat(stash_buffer,stash_buffer_tmp);
Letme 0:272c70e2366c 171 return 1;
Letme 0:272c70e2366c 172 }
Letme 0:272c70e2366c 173
Letme 0:272c70e2366c 174 /**
Letme 5:f232b826e1f2 175 * Log_pop function sends everything log_stash stashed. Stash buffer is defined outside of function
Letme 5:f232b826e1f2 176 * and pointer to memory space is passed into it. Make sure you have a string buffer on
Letme 5:f232b826e1f2 177 * passed location, as there is still not enough checks against that
Letme 5:f232b826e1f2 178 *
Letme 3:e1ed8ae7691e 179 * @param[in] plc Place to where you pop stashed messages
Letme 4:9360fdf3a818 180 * @param[in] *stash_buffer Place where stashed messages were saved
Letme 4:9360fdf3a818 181 * @param[in] stash_buffer_len how many characters can be saved on stashed message buffer
Letme 1:8837abc3f763 182 *
Letme 3:e1ed8ae7691e 183 * @retval 1 for success
Letme 3:e1ed8ae7691e 184 * @retval 2 for partial printout - did not send everything. You need to recall the function within timer so that you do not flood the serial port. So far it is only on BTSerial.
Letme 1:8837abc3f763 185 * @retval -ERR errno.h error message
Letme 5:f232b826e1f2 186 *
Letme 0:272c70e2366c 187 */
Letme 4:9360fdf3a818 188 int32_t log_pop(uint8_t plc,char *stash_buffer,size_t stash_buffer_len) {
Letme 4:9360fdf3a818 189 if((stash_buffer == NULL) || (stash_buffer_len == 0))
Letme 4:9360fdf3a818 190 {
Letme 4:9360fdf3a818 191 return -EINVAL;
Letme 4:9360fdf3a818 192 }
Letme 4:9360fdf3a818 193
Letme 3:e1ed8ae7691e 194 char *tmp_needle;
Letme 3:e1ed8ae7691e 195 size_t tmp_len;
Letme 3:e1ed8ae7691e 196
Letme 1:8837abc3f763 197 switch(plc) {
Letme 1:8837abc3f763 198 case L_SERIAL:
Letme 1:8837abc3f763 199 if(logSerial.writeable()) {
Letme 3:e1ed8ae7691e 200 logSerial.printf("%s",stash_buffer);
Letme 5:f232b826e1f2 201
Letme 5:f232b826e1f2 202 //clear stash buffer
Letme 5:f232b826e1f2 203 int i;
Letme 5:f232b826e1f2 204 for(i=0;i<stash_buffer_len;++i) {
Letme 5:f232b826e1f2 205 stash_buffer[i]=0;
Letme 5:f232b826e1f2 206 }
Letme 1:8837abc3f763 207 } else {
Letme 1:8837abc3f763 208 return -EBUSY;
Letme 1:8837abc3f763 209 }
Letme 1:8837abc3f763 210 break;
Letme 1:8837abc3f763 211 case L_FILE:
Letme 1:8837abc3f763 212 break;
Letme 1:8837abc3f763 213 case L_LED:
Letme 1:8837abc3f763 214 // find out what we want here -morse code would be fun ;)
Letme 1:8837abc3f763 215 break;
Letme 3:e1ed8ae7691e 216 case L_BTSERIAL:
Letme 3:e1ed8ae7691e 217 if(BTSerial.writeable()) {
Letme 3:e1ed8ae7691e 218 // big chunk of text is not OK - add some delay between it
Letme 3:e1ed8ae7691e 219 tmp_needle=strstr(stash_buffer,endline);
Letme 3:e1ed8ae7691e 220 if(tmp_needle != NULL)
Letme 3:e1ed8ae7691e 221 {
Letme 3:e1ed8ae7691e 222 // we have found a end line - now print out up to this end line
Letme 3:e1ed8ae7691e 223 tmp_len = (tmp_needle+strlen(endline))-stash_buffer;
Letme 3:e1ed8ae7691e 224 // we pray for complete printf definition
Letme 3:e1ed8ae7691e 225 BTSerial.printf("%.*s", tmp_len,stash_buffer);
Letme 3:e1ed8ae7691e 226 // move whole array to remove out the line needle is increased before tmp_len to include the endline string
Letme 4:9360fdf3a818 227 memmove(stash_buffer,tmp_needle+strlen(endline),stash_buffer_len-tmp_len);
Letme 3:e1ed8ae7691e 228 return 2;
Letme 3:e1ed8ae7691e 229 }
Letme 3:e1ed8ae7691e 230 } else {
Letme 3:e1ed8ae7691e 231 return -EBUSY;
Letme 3:e1ed8ae7691e 232 }
Letme 3:e1ed8ae7691e 233 break;
Letme 1:8837abc3f763 234 default:
Letme 1:8837abc3f763 235 return -EINVAL;
Letme 0:272c70e2366c 236
Letme 1:8837abc3f763 237 }
Letme 1:8837abc3f763 238
Letme 1:8837abc3f763 239 return 1;
Letme 2:9d04753a3ad2 240 }
Letme 2:9d04753a3ad2 241 /**
Letme 2:9d04753a3ad2 242 * @}
Letme 2:9d04753a3ad2 243 */