diff --git a/Display.cpp b/Display.cpp index 5477353..5454a92 100644 --- a/Display.cpp +++ b/Display.cpp @@ -27,10 +27,10 @@ Display::~Display() void Display::begin() { - logger.info(TAG, "initializing display"); + dlog.info(TAG, F("initializing display")); if (!_dsp.init()) { - logger.error(TAG, "display.init() failed!"); + dlog.error(TAG, F("display.init() failed!")); } _dsp.flipScreenVertically(); font(ArialMT_Plain_10); diff --git a/Display.h b/Display.h index 4c838e0..98c9bcf 100644 --- a/Display.h +++ b/Display.h @@ -28,6 +28,7 @@ public: void display(); void align(OLEDDISPLAY_TEXT_ALIGNMENT alignment); void font(const char* fontData); + void print(int16_t x, int16_t y, const char* fmt, ...); private: SSD1306Wire _dsp; diff --git a/ESPNTPServer.cpp b/ESPNTPServer.cpp index 979b0e5..08a4229 100644 --- a/ESPNTPServer.cpp +++ b/ESPNTPServer.cpp @@ -22,6 +22,7 @@ #include "ESPNTPServer.h" #include "Log.h" +#include "DLogPrintWriter.h" #include "GPS.h" #include "NTP.h" @@ -30,18 +31,20 @@ GPS gps(Serial, SYNC_PIN); NTP ntp(gps); Display display(gps, ntp, SDA_PIN, SCL_PIN); +DLog& dlog = DLog::getLog(); const char* SETUP_TAG = "setup"; const char* LOOP_TAG = "loop"; -void logTimeFirst(Print* print) +void logTimeFirst(DLogBuffer& buffer, DLogLevel level) { - static struct timeval tv; + (void)level; // not used + struct timeval tv; + struct tm tm; gps.getTime(&tv); - static struct tm tm; gmtime_r(&tv.tv_sec, &tm); - print->printf("%04d/%02d/%02d %02d:%02d:%02d.%06ld ", + buffer.printf(F("%04d/%02d/%02d %02d:%02d:%02d.%06ld "), tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, @@ -54,25 +57,29 @@ void logTimeFirst(Print* print) void setup() { delay(5000); // delay for IDE to re-open serial - Serial1.begin(115200); - logger.setSize(256); - logger.setPrint(&Serial1); - logger.setPreFunc(&logTimeFirst); - logger.info(SETUP_TAG, "Startup!"); - logger.info(SETUP_TAG, "initializing display"); + // + // Setup DLog with Serial1, set the pre function to add the date/time + // + Serial1.begin(115200); + dlog.begin(new DLogPrintWriter(Serial1)); + dlog.setPreFunc(&logTimeFirst); + + dlog.info(SETUP_TAG, F("Startup!")); + + dlog.info(SETUP_TAG, F("initializing display")); display.begin(); - logger.info(SETUP_TAG, "initializing serial for GPS"); + dlog.info(SETUP_TAG, F("initializing serial for GPS")); Serial.begin(9600); Serial.swap(); - logger.info(SETUP_TAG, "initializing GPS"); + dlog.info(SETUP_TAG, F("initializing GPS")); gps.begin(); display.process(); #if !defined(USE_NO_WIFI) - logger.info(SETUP_TAG, "initializing wifi"); + dlog.info(SETUP_TAG, F("initializing wifi")); #if 0 WiFiManager wifi; wifi.setDebugStream(Serial1); @@ -88,7 +95,7 @@ void setup() display.process(); - logger.info(SETUP_TAG, "initializing NTP"); + dlog.info(SETUP_TAG, F("initializing NTP")); ntp.begin(); } @@ -122,14 +129,14 @@ void loop() status = ""; break; } - logger.info(LOOP_TAG, "wifi status change %d -> %d '%s'", last_wifi_status, wifi_status, status); + dlog.info(LOOP_TAG, F("wifi status change %d -> %d '%s'"), last_wifi_status, wifi_status, status); last_wifi_status = wifi_status; } IPAddress ip = WiFi.localIP(); if (ip != last_ip) { - logger.warning(LOOP_TAG, "ip address change %s -> %s", last_ip.toString().c_str(), ip.toString().c_str()); + dlog.warning(LOOP_TAG, F("ip address change %s -> %s"), last_ip.toString().c_str(), ip.toString().c_str()); last_ip = ip; } @@ -138,22 +145,12 @@ void loop() static time_t last_seconds; struct timeval tv; gps.getTime(&tv); + if (tv.tv_sec != last_seconds) { - struct tm tm; - gmtime_r(&tv.tv_sec, &tm); - char ts[64]; - snprintf(ts, 63, "%04d/%02d/%02d %02d:%02d:%02d.%06ld", - tm.tm_year+1900, - tm.tm_mon+1, - tm.tm_mday, - tm.tm_hour, - tm.tm_min, - tm.tm_sec, - tv.tv_usec); if (tv.tv_sec != last_seconds && ((tv.tv_sec % 300) == 0 || gps.getValidDelay())) { - logger.info("loop", "jitter:%lu valid_count:%lu valid:%s gpsvalid:%s numsat:%d heap:%ld valid_delay:%d", + dlog.info("loop", F("jitter:%lu valid_count:%lu valid:%s gpsvalid:%s numsat:%d heap:%ld valid_delay:%d"), gps.getJitter(), gps.getValidCount(), gps.isValid() ? "true" : "false", @@ -165,7 +162,7 @@ void loop() if (tv.tv_sec < last_seconds) { - logger.warning(LOOP_TAG, "%s: OOPS: time went backwards: last:%lu now:%lu\n", ts, last_seconds, tv.tv_sec); + dlog.warning(LOOP_TAG, F("OOPS: time went backwards: last:%lu now:%lu delta:%ld"), last_seconds, tv.tv_sec, tv.tv_sec-last_seconds); } display.process(); diff --git a/GPS.cpp b/GPS.cpp index d1f1e79..4c31dfe 100644 --- a/GPS.cpp +++ b/GPS.cpp @@ -110,7 +110,7 @@ void GPS::process() { if (_reason[0] != '\0') { - logger.warning(TAG, "REASON: %s", _reason); + dlog.warning(TAG, F("REASON: %s"), _reason); _reason[0] = '\0'; } @@ -120,7 +120,7 @@ void GPS::process() { struct timeval tv; getTime(&tv); - logger.debug(TAG, "'%s'", _nmea.getSentence()); + dlog.debug(TAG, F("'%s'"), _nmea.getSentence()); const char * id = _nmea.getMessageID(); @@ -148,11 +148,11 @@ void GPS::process() { _seconds = new_seconds; invalidate("seconds adjusted!"); - logger.info(TAG, "adjusting seconds from %lu to %lu from:'%s'", old_seconds, new_seconds, _nmea.getSentence()); + dlog.info(TAG, F("adjusting seconds from %lu to %lu from:'%s'"), old_seconds, new_seconds, _nmea.getSentence()); } else { - logger.debug(TAG, "ignoring late NMEA time: '%s'",_nmea.getSentence()); + dlog.debug(TAG, F("ignoring late NMEA time: '%s'"),_nmea.getSentence()); } } @@ -169,7 +169,7 @@ void GPS::process() { _valid_delay = VALID_DELAY; _gps_valid = true; - logger.info(TAG, "GPS valid!"); + dlog.info(TAG, F("GPS valid!")); } } else /* nmea not valid or sat count < 4 */ diff --git a/Log.cpp b/Log.cpp deleted file mode 100644 index d756120..0000000 --- a/Log.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Log.cpp - * - * Copyright 2017 Christopher B. Liebman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Created on: Mar 2, 2018 - * Author: chris.l - */ -#include "Arduino.h" -#include "Log.h" - -static const char* level_names[LOG_LEVEL_MAX] = { - "NONE", - "ERROR", - "WARN", - "INFO", - "DEBUG", - "TRACE" -}; - -Log& Log::getLog() -{ - static Log log; - return log; -} - -Log::Log() : - _level(LOG_LEVEL_INFO), - _size(LOG_MAX_SIZE), - _buffer(nullptr), - _print(nullptr) -{ -} - -Log::~Log() -{ - if (_buffer != nullptr) - { - delete[] _buffer; - } -} - -void Log::setSize(size_t size) -{ - _size = size; - if (_buffer) - { - delete[] _buffer; - _buffer = nullptr; - } -} - -void Log::setLevel(LogLevel level) -{ - _level = level; -} - -void Log::setLevel(const char* name, LogLevel level) -{ - _levels[name] = level; -} - -void Log::setPrint(Print *print) -{ - _print = print; -} -void Log::setPreFunc(std::function func) -{ - pre_func = func; -} - -void Log::error(const char* name, const char* fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - print(name, LOG_LEVEL_ERROR, fmt, ap); - va_end(ap); -} - -void Log::warning(const char* name, const char* fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - print(name, LOG_LEVEL_WARNING, fmt, ap); - va_end(ap); -} - -void Log::info(const char* name, const char* fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - print(name, LOG_LEVEL_INFO, fmt, ap); - va_end(ap); -} - -void Log::debug(const char* name, const char* fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - print(name, LOG_LEVEL_DEBUG, fmt, ap); - va_end(ap); -} - -void Log::trace(const char* name, const char* fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - print(name, LOG_LEVEL_TRACE, fmt, ap); - va_end(ap); -} - -void Log::print(const char* name, LogLevel level, const char* fmt, va_list ap) -{ - LogLevel limit = _level; - if (_levels.find(name) != _levels.end()) - { - limit = _levels[name]; - } - - if (level > limit) - { - return; - } - - // - // allocate the buffer on first use - // - if (_buffer == nullptr) - { - _buffer = new char[_size]; - } - - if (_print == nullptr) - { - _print = &Serial; - } - - vsnprintf(_buffer, _size-1, fmt, ap); - - if (pre_func) - { - pre_func(_print); - } - - _print->printf("%s %5s %s\n", name, level_names[level], _buffer); -} - -Log& logger = Log::getLog(); diff --git a/Log.h b/Log.h index 3fc5ce4..dc8815f 100644 --- a/Log.h +++ b/Log.h @@ -22,61 +22,8 @@ #ifndef LOG_H_ #define LOG_H_ -#include "Print.h" -#include -#include -#include +#include "DLog.h" -typedef enum log_level -{ - LOG_LEVEL_NONE = 0, - LOG_LEVEL_ERROR, - LOG_LEVEL_WARNING, - LOG_LEVEL_INFO, - LOG_LEVEL_DEBUG, - LOG_LEVEL_TRACE, - LOG_LEVEL_MAX, -} LogLevel; - -#define LOG_MAX_SIZE 80 -#define LOG_LEVEL_DEFAULT LOG_LEVEL_INFO - -class Log -{ -public: - static Log& getLog(); - - void setSize(size_t size); - void setLevel(LogLevel level); - void setLevel(const char* name, LogLevel level); - void setPrint(Print *print); - void setPreFunc(std::function func); - - void error(const char* name, const char* fmt, ...); - void warning(const char* name, const char* fmt, ...); - void info(const char* name, const char* fmt, ...); - void debug(const char* name, const char* fmt, ...); - void trace(const char* name, const char* fmt, ...); - - // we don't allow copying this guy! - Log(const Log&) = delete; - Log& operator=(const Log&) = delete; - -private: - LogLevel _level; // default log level - size_t _size; - char* _buffer; - std::map _levels; - Print* _print; - - std::function pre_func; - - - Log(); - virtual ~Log(); - void print(const char* name, LogLevel level, const char*fmt, va_list ap); -}; - -extern Log& logger; +extern DLog& dlog; #endif /* LOG_H_ */ diff --git a/NTP.cpp b/NTP.cpp index f5a6712..51b6251 100644 --- a/NTP.cpp +++ b/NTP.cpp @@ -125,10 +125,11 @@ void NTP::begin() _precision = computePrecision(); while (!_udp.listen(NTP_PORT)) { - logger.error(TAG, "failed to listen on port %d! Will retry in a bit...", NTP_PORT); + dlog.error(TAG, F("failed to listen on port %d! Will retry in a bit..."), NTP_PORT); delay(1000); - logger.warning(TAG, "setup: retrying!"); + dlog.warning(TAG, F("setup: retrying!")); } + using namespace std::placeholders; // for _1, _2, _3... _udp.onPacket(std::bind( &NTP::ntp, this, _1)); @@ -146,7 +147,7 @@ int8_t NTP::computePrecision() double total = (double)(end - start) / 1000000.0; double time = total / PRECISION_COUNT; double prec = log2(time); - logger.info(TAG, "computePrecision: total:%f time:%f prec:%f (%d)", total, time, prec, (int8_t)prec); + dlog.info(TAG, F("computePrecision: total:%f time:%f prec:%f (%d)"), total, time, prec, (int8_t)prec); return (int8_t)prec; } @@ -168,13 +169,13 @@ void NTP::ntp(AsyncUDPPacket& aup) getNTPTime(&recv_time); if (aup.length() != sizeof(NTPPacket)) { - logger.warning(TAG, "recievePacket: ignoring packet with bad length: %d < %d", aup.length(), sizeof(NTPPacket)); + dlog.warning(TAG, F("recievePacket: ignoring packet with bad length: %d < %d"), aup.length(), sizeof(NTPPacket)); return; } if (!_gps.isValid()) { - logger.warning(TAG, "recievePacket: GPS data not valid!"); + dlog.warning(TAG, F("recievePacket: GPS data not valid!")); return; } diff --git a/WireUtils.cpp b/WireUtils.cpp index f0ecf31..63c1cbe 100644 --- a/WireUtils.cpp +++ b/WireUtils.cpp @@ -43,7 +43,7 @@ WireUtilsC::WireUtilsC() */ int WireUtilsC::clearBus() { - logger.warning(TAG, "WireUtils::ClearBus: attempting to clean i2c bus"); + dlog.warning(TAG, F("WireUtils::ClearBus: attempting to clean i2c bus")); #if defined(TWCR) && defined(TWEN) TWCR &= ~(_BV(TWEN)); //Disable the Atmel 2-Wire interface so we can control the SDA and SCL pins directly #endif @@ -53,7 +53,7 @@ int WireUtilsC::clearBus() boolean SCL_LOW = (digitalRead(SCL) == LOW); // Check is SCL is Low. if (SCL_LOW) { //If it is held low Arduno cannot become the I2C master. - logger.error(TAG, "WireUtils::ClearBus: Failed! SCL held low!"); + dlog.error(TAG, F("WireUtils::ClearBus: Failed! SCL held low!")); return 1; //I2C bus error. Could not clear SCL clock line held low } @@ -82,14 +82,14 @@ int WireUtilsC::clearBus() } if (SCL_LOW) { // still low after 2 sec error - logger.error(TAG, "WireUtils::ClearBus: Failed! SCL clock line held low by slave clock stretch for >2sec"); + dlog.error(TAG, F("WireUtils::ClearBus: Failed! SCL clock line held low by slave clock stretch for >2sec")); return 2; // I2C bus error. Could not clear. SCL clock line held low by slave clock stretch for >2sec } SDA_LOW = (digitalRead(SDA) == LOW); // and check SDA input again and loop } if (SDA_LOW) { // still low - logger.error(TAG, "WireUtils::ClearBus: Failed! SDA data line still held low"); + dlog.error(TAG, F("WireUtils::ClearBus: Failed! SDA data line still held low")); return 3; // I2C bus error. Could not clear. SDA data line held low } @@ -104,7 +104,7 @@ int WireUtilsC::clearBus() delayMicroseconds(10); // x. wait >5uS pinMode(SDA, INPUT); // and reset pins as tri-state inputs which is the default state on reset pinMode(SCL, INPUT); - logger.info(TAG, "WireUtils::ClearBus: Success!"); + dlog.info(TAG, F("WireUtils::ClearBus: Success!")); return 0; // all ok }