forked from bullshit/Arduino-logging-library
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLogging.h
276 lines (249 loc) · 7 KB
/
Logging.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
#ifndef LOGGING_H
#define LOGGING_H
#include <inttypes.h>
#include <stdarg.h>
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#define LOG_LEVEL_NOOUTPUT 0
#define LOG_LEVEL_ERRORS 1
#define LOG_LEVEL_WARNINGS 2
#define LOG_LEVEL_INFOS 3
#define LOG_LEVEL_DEBUG 4
#define LOG_LEVEL_VERBOSE 5
// default loglevel if nothing is set from user
#ifndef LOGLEVEL
#define LOGLEVEL LOG_LEVEL_DEBUG
#endif
#define CR "\r\n"
#define LOGGING_VERSION 1
typedef void (*char_printer_fn_t)(const char c);
class LogPrinter : public Print {
char_printer_fn_t _printer;
public:
LogPrinter(char_printer_fn_t printer) {
_printer = printer;
}
virtual size_t write(uint8_t c) {
_printer(c);
return 1;
}
};
typedef void (*string_printer_fn_t)(const char *s);
class LogBufferedPrinter : public Print {
string_printer_fn_t _printer;
char *_buffer;
size_t _size;
size_t _index;
public:
LogBufferedPrinter(string_printer_fn_t printer, char *buffer, size_t size) {
// assert(printer!=NULL);
// assert(buffer!=NULL);
// assert(size>1);
_printer = printer;
_buffer = buffer;
_size = size;
}
virtual size_t write(uint8_t c) {
_buffer[_index++] = c;
if (c=='\n' || (_index+1)==_size) {
_buffer[_index] = 0;
_printer(_buffer);
_index = 0;
}
return 1;
}
};
/*!
* Logging is a helper class to output informations over
* RS232. If you know log4j or log4net, this logging class
* is more or less similar ;-) <br>
* Different loglevels can be used to extend or reduce output
* All methods are able to handle any number of output parameters.
* All methods print out a formated string (like printf).<br>
* To reduce output and program size, reduce loglevel.
* <br>
* Output format string can contain below wildcards. Every wildcard
* must be start with percent sign (\%)
*
* <b>Depending on loglevel, source code is excluded from compile !</b><br>
* <br>
* <b>Wildcards</b><br>
* <ul>
* <li><b>\%s</b> replace with an string (char*)</li>
* <li><b>\%c</b> replace with an character</li>
* <li><b>\%d</b> replace with an integer value</li>
* <li><b>\%l</b> replace with an long value</li>
* <li><b>\%x</b> replace and convert integer value into hex</li>
* <li><b>\%X</b> like %x but combine with <b>0x</b>123AB</li>
* <li><b>\%b</b> replace and convert integer value into binary</li>
* <li><b>\%B</b> like %x but combine with <b>0b</b>10100011</li>
* <li><b>\%t</b> replace and convert boolean value into <b>"t"</b> or <b>"f"</b></li>
* <li><b>\%T</b> like %t but convert into <b>"true"</b> or <b>"false"</b></li>
* <li><b>\%f</b> replace with a double value</li>
* <li><b>\\%</b> to escape an % char</li>
* </ul><br>
* <b>Loglevels</b><br>
* <table border="0">
* <tr><td>0</td><td>LOG_LEVEL_NOOUTPUT</td><td>no output </td></tr>
* <tr><td>1</td><td>LOG_LEVEL_ERRORS</td><td>only errors </td></tr>
* <tr><td>2</td><td>LOG_LEVEL_INFOS</td><td>errors and info </td></tr>
* <tr><td>3</td><td>LOG_LEVEL_DEBUG</td><td>errors, info and debug </td></tr>
* <tr><td>4</td><td>LOG_LEVEL_VERBOSE</td><td>all </td></tr>
* </table>
* <br>
* <h1>History</h1><br>
* <table border="0">
* <tr><td>01 FEB 2012</td><td>initial release</td></tr>
* <tr><td>06 MAR 2012</td><td>implement a preinstanciated object (like in Wire, ...)</td></tr>
* <tr><td></td><td>method init get now loglevel and baud parameter</td></tr>
*/
class Logging {
private:
int _level;
Print *_printer;
public:
/*!
* default Constructor
*/
Logging(){} ;
/**
* Initializing, must be called as first.
* \param level the log level
* \param printer the function called to print a character, instead of Serial
*/
void Init(int level, Print &printer);
/**
* Output an error message. Output message contains
* ERROR: followed by original msg
* Error messages are printed out, at every loglevel
* except 0 ;-)
* \param msg format string to output
* \param ... any number of variables
* \return void
*/
template <class T> void Error(T msg, ...){
if (LOG_LEVEL_ERRORS <= _level) {
va_list args;
va_start(args, msg);
print(F("ERROR: "),args); // args unused
print(msg,args);
va_end(args);
}
}
template <class T> void ErrorArgs(T msg, va_list args) {
if (LOG_LEVEL_ERRORS <= _level) {
print(msg,args);
}
}
/**
* Output a warning message. Output message contains
* WARNING: followed by original msg
* Warning messages are printed out at l
* loglevels >= LOG_LEVEL_WARNINGS
* \param msg format string to output
* \param ... any number of variables
* \return void
*/
template <class T> void Warn(T msg, ...){
if (LOG_LEVEL_WARNINGS <= _level) {
va_list args;
va_start(args, msg);
print(F("WARNING: "),args); // args unused
print(msg,args);
va_end(args);
}
}
template <class T> void WarnArgs(T msg, va_list args) {
if (LOG_LEVEL_WARNINGS <= _level) {
print(msg,args);
}
}
/**
* Output an info message. Output message contains
* Info messages are printed out at l
* loglevels >= LOG_LEVEL_INFOS
*
* \param msg format string to output
* \param ... any number of variables
* \return void
*/
template <class T> void Info(T msg, ...){
if (LOG_LEVEL_INFOS <= _level) {
va_list args;
va_start(args, msg);
print(msg,args);
va_end(args);
}
}
template <class T> void InfoArgs(T msg, va_list args) {
if (LOG_LEVEL_INFOS <= _level) {
print(msg,args);
}
}
/**
* Output an debug message. Output message contains
* Debug messages are printed out at l
* loglevels >= LOG_LEVEL_DEBUG
*
* \param msg format string to output
* \param ... any number of variables
* \return void
*/
template <class T> void Debug(T msg, ...){
if (LOG_LEVEL_DEBUG <= _level) {
va_list args;
va_start(args, msg);
print(F("debug: "),args); // args unused
print(msg,args);
va_end(args);
}
}
// Allows continued debug messages with no "DEBUG:" prefix
template <class T> void Debug_(T msg, ...){
if (LOG_LEVEL_DEBUG <= _level) {
va_list args;
va_start(args, msg);
print(msg,args);
va_end(args);
}
}
template <class T> void DebugArgs(T msg, va_list args) {
if (LOG_LEVEL_DEBUG <= _level) {
print(msg,args);
}
}
/**
* Output an verbose message. Output message contains
* Debug messages are printed out at l
* loglevels >= LOG_LEVEL_VERBOSE
*
* \param msg format string to output
* \param ... any number of variables
* \return void
*/
template <class T> void Verbose(T msg, ...){
if (LOG_LEVEL_VERBOSE <= _level) {
va_list args;
va_start(args, msg);
print (F("verbose: "),args); // args unused
print(msg,args);
va_end(args);
}
}
template <class T> void VerboseArgs(T msg, va_list args) {
if (LOG_LEVEL_VERBOSE <= _level) {
print(msg,args);
}
}
private:
void print(const char *format, va_list args);
#if !defined(PLATFORM_NATIVE)
void print(const __FlashStringHelper *format, va_list args);
#endif
void printFormat(const char format, va_list *args, const int len);
};
extern Logging Log;
#endif