diff --git a/lib/log/GWLog.cpp b/lib/log/GWLog.cpp index 6601f2a..936e876 100644 --- a/lib/log/GWLog.cpp +++ b/lib/log/GWLog.cpp @@ -37,9 +37,12 @@ void GwLog::logString(const char *fmt,...){ xSemaphoreGive(locker); } void GwLog::logDebug(int level,const char *fmt,...){ - if (level > logLevel) return; va_list args; va_start(args,fmt); + logDebug(level,fmt,args); +} +void GwLog::logDebug(int level,const char *fmt,va_list args){ + if (level > logLevel) return; xSemaphoreTake(locker, portMAX_DELAY); recordCounter++; vsnprintf(buffer,bufferSize-1,fmt,args); diff --git a/lib/log/GwLog.h b/lib/log/GwLog.h index e04c7b5..d4ea76d 100644 --- a/lib/log/GwLog.h +++ b/lib/log/GwLog.h @@ -27,6 +27,7 @@ class GwLog{ void setWriter(GwLogWriter *writer); void logString(const char *fmt,...); void logDebug(int level, const char *fmt,...); + void logDebug(int level, const char *fmt,va_list ap); int isActive(int level){return level <= logLevel;}; void flush(); void setLevel(int level){this->logLevel=level;} diff --git a/lib/nmea2ktwai/Nmea2kTwai.cpp b/lib/nmea2ktwai/Nmea2kTwai.cpp index e345a8a..73fb256 100644 --- a/lib/nmea2ktwai/Nmea2kTwai.cpp +++ b/lib/nmea2ktwai/Nmea2kTwai.cpp @@ -3,22 +3,10 @@ #include "driver/twai.h" #include "GwLog.h" -#define TWAI_DEBUG 0 -#if TWAI_DEBUG == 1 - #define TWAI_LOG(...) LOG_DEBUG(__VA_ARGS__) - #define TWAI_LDEBUG(...) -#else - #if TWAI_DEBUG == 2 - #define TWAI_LOG(...) LOG_DEBUG(__VA_ARGS__) - #define TWA_LDEBUG(...) LOG_DEBUG(__VA_ARGS__) - #else - #define TWAI_LOG(...) - #define TWAI_LDEBUG(...) - #endif -#endif +#define LOGID(id) ((id >> 8) & 0x1ffff) -Nmea2kTwai::Nmea2kTwai(gpio_num_t _TxPin, gpio_num_t _RxPin,GwLog *l): - tNMEA2000(),RxPin(_RxPin),TxPin(_TxPin),logger(l) +Nmea2kTwai::Nmea2kTwai(gpio_num_t _TxPin, gpio_num_t _RxPin): + tNMEA2000(),RxPin(_RxPin),TxPin(_TxPin) { } @@ -32,21 +20,21 @@ bool Nmea2kTwai::CANSendFrame(unsigned long id, unsigned char len, const unsigne memcpy(message.data,buf,len); esp_err_t rt=twai_transmit(&message,0); if (rt != ESP_OK){ - TWAI_LOG(GwLog::DEBUG,"twai transmit for %ld failed: %x",(id & 0x1ffff),(int)rt); + logDebug(LOG_DEBUG,"twai transmit for %ld failed: %x",LOGID(id),(int)rt); return false; } - TWAI_LDEBUG(GwLog::DEBUG,"twai transmit id %ld, len %d",(id & 0x1ffff),(int)len); + logDebug(LOG_MSG,"twai transmit id %ld, len %d",LOGID(id),(int)len); return true; } bool Nmea2kTwai::CANOpen() { esp_err_t rt=twai_start(); if (rt != ESP_OK){ - LOG_DEBUG(GwLog::ERROR,"CANOpen failed: %x",(int)rt); + logDebug(LOG_ERR,"CANOpen failed: %x",(int)rt); return false; } else{ - LOG_DEBUG(GwLog::LOG,"CANOpen ok"); + logDebug(LOG_INFO,"CANOpen ok"); } return true; } @@ -63,10 +51,10 @@ bool Nmea2kTwai::CANGetFrame(unsigned long &id, unsigned char &len, unsigned cha id=message.identifier; len=message.data_length_code; if (len > 8){ - TWAI_LOG(GwLog::ERROR,"twai: received invalid message %lld, len %d",id,len); + logDebug(LOG_DEBUG,"twai: received invalid message %lld, len %d",LOGID(id),len); len=8; } - TWAI_LDEBUG(GwLog::DEBUG,"twai rcv id=%ld,len=%d, ext=%d",message.identifier,message.data_length_code,message.extd); + logDebug(LOG_MSG,"twai rcv id=%ld,len=%d, ext=%d",LOGID(message.identifier),message.data_length_code,message.extd); if (! message.rtr){ memcpy(buf,message.data,message.data_length_code); } @@ -79,10 +67,10 @@ void Nmea2kTwai::initDriver(){ twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL(); esp_err_t rt=twai_driver_install(&g_config, &t_config, &f_config); if (rt == ESP_OK) { - LOG_DEBUG(GwLog::LOG,"twai driver initialzed, rx=%d,tx=%d",(int)RxPin,(int)TxPin); + logDebug(LOG_INFO,"twai driver initialzed, rx=%d,tx=%d",(int)RxPin,(int)TxPin); } else{ - LOG_DEBUG(GwLog::ERROR,"twai driver init failed: %x",(int)rt); + logDebug(LOG_ERR,"twai driver init failed: %x",(int)rt); } } // This will be called on Open() before any other initialization. Inherit this, if buffers can be set for the driver @@ -93,38 +81,38 @@ void Nmea2kTwai::InitCANFrameBuffers() tNMEA2000::InitCANFrameBuffers(); } -Nmea2kTwai::STATE Nmea2kTwai::getState(){ +Nmea2kTwai::Status Nmea2kTwai::getStatus(){ twai_status_info_t state; + Status rt; if (twai_get_status_info(&state) != ESP_OK){ - return ST_ERROR; + return rt; } switch(state.state){ case TWAI_STATE_STOPPED: - return ST_STOPPED; + rt.state=ST_STOPPED; + break; case TWAI_STATE_RUNNING: - return ST_RUNNING; + rt.state=ST_RUNNING; + break; case TWAI_STATE_BUS_OFF: - return ST_BUS_OFF; + rt.state=ST_BUS_OFF; + break; case TWAI_STATE_RECOVERING: - return ST_RECOVERING; - } - return ST_ERROR; -} -Nmea2kTwai::ERRORS Nmea2kTwai::getErrors(){ - ERRORS rt; - twai_status_info_t state; - if (twai_get_status_info(&state) != ESP_OK){ - return rt; + rt.state=ST_RECOVERING; + break; } rt.rx_errors=state.rx_error_counter; rt.tx_errors=state.tx_error_counter; rt.tx_failed=state.tx_failed_count; + rt.rx_missed=state.rx_missed_count; + rt.rx_overrun=state.rx_overrun_count; return rt; } + bool Nmea2kTwai::startRecovery(){ esp_err_t rt=twai_driver_uninstall(); if (rt != ESP_OK){ - LOG_DEBUG(GwLog::ERROR,"twai: deinit for recovery failed with %x",(int)rt); + logDebug(LOG_ERR,"twai: deinit for recovery failed with %x",(int)rt); } initDriver(); bool frt=CANOpen(); diff --git a/lib/nmea2ktwai/Nmea2kTwai.h b/lib/nmea2ktwai/Nmea2kTwai.h index 069e247..0fa9a92 100644 --- a/lib/nmea2ktwai/Nmea2kTwai.h +++ b/lib/nmea2ktwai/Nmea2kTwai.h @@ -5,7 +5,7 @@ class Nmea2kTwai : public tNMEA2000{ public: - Nmea2kTwai(gpio_num_t _TxPin, gpio_num_t _RxPin,GwLog *logger); + Nmea2kTwai(gpio_num_t _TxPin, gpio_num_t _RxPin); typedef enum{ ST_STOPPED, ST_RUNNING, @@ -14,15 +14,23 @@ class Nmea2kTwai : public tNMEA2000{ ST_ERROR } STATE; typedef struct{ + //see https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/twai.html#_CPPv418twai_status_info_t uint32_t rx_errors=0; uint32_t tx_errors=0; uint32_t tx_failed=0; - } ERRORS; - STATE getState(); - ERRORS getErrors(); + uint32_t rx_missed=0; + uint32_t rx_overrun=0; + STATE state=ST_ERROR; + } Status; + Status getStatus(); bool startRecovery(); static const char * stateStr(const STATE &st); virtual bool CANOpen(); + virtual ~Nmea2kTwai(){}; + static const int LOG_ERR=0; + static const int LOG_INFO=1; + static const int LOG_DEBUG=2; + static const int LOG_MSG=3; protected: // Virtual functions for different interfaces. Currently there are own classes // for Arduino due internal CAN (NMEA2000_due), external MCP2515 SPI CAN bus controller (NMEA2000_mcp), @@ -32,14 +40,13 @@ class Nmea2kTwai : public tNMEA2000{ // This will be called on Open() before any other initialization. Inherit this, if buffers can be set for the driver // and you want to change size of library send frame buffer size. See e.g. NMEA2000_teensy.cpp. virtual void InitCANFrameBuffers(); - + virtual void logDebug(int level,const char *fmt,...){} private: void initDriver(); gpio_num_t TxPin; gpio_num_t RxPin; - GwLog *logger; }; #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index fa48026..8830e4f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -110,7 +110,22 @@ GwLog logger(LOGLEVEL,NULL); GwConfigHandler config(&logger); #include "Nmea2kTwai.h" -Nmea2kTwai &NMEA2000=*(new Nmea2kTwai(ESP32_CAN_TX_PIN,ESP32_CAN_RX_PIN,&logger)); +class Nmea2kTwaiLog : public Nmea2kTwai{ + private: + GwLog* logger; + public: + Nmea2kTwaiLog(gpio_num_t _TxPin, gpio_num_t _RxPin, GwLog *l): + Nmea2kTwai(_TxPin,_RxPin),logger(l){} + virtual void logDebug(int level, const char *fmt,...){ + va_list args; + va_start(args,fmt); + if (level > 2) level++; //error+info+debug are similar, map msg to 4 + logger->logDebug(level,fmt,args); + } +}; + + +Nmea2kTwai &NMEA2000=*(new Nmea2kTwaiLog(ESP32_CAN_TX_PIN,ESP32_CAN_RX_PIN,&logger)); #ifdef GWBUTTON_PIN bool fixedApPass=false; @@ -354,7 +369,7 @@ public: protected: virtual void processRequest() { - GwJsonDocument status(256 + + GwJsonDocument status(290 + countNMEA2KIn.getJsonSize()+ countNMEA2KOut.getJsonSize() + channels.getJsonSize() @@ -370,6 +385,8 @@ protected: status["salt"] = buffer; status["fwtype"]= firmwareType; status["heap"]=(long)xPortGetFreeHeapSize(); + Nmea2kTwai::Status n2kState=NMEA2000.getStatus(); + status["n2kstate"]=NMEA2000.stateStr(n2kState.state); //nmea0183Converter->toJson(status); countNMEA2KIn.toJson(status); countNMEA2KOut.toJson(status); @@ -843,15 +860,20 @@ void loop() { } if (now > (lastCanRecovery + CAN_RECOVERY_PERIOD)){ lastCanRecovery=now; - Nmea2kTwai::STATE canState=NMEA2000.getState(); - Nmea2kTwai::ERRORS canErrors=NMEA2000.getErrors(); - logger.logDebug(GwLog::DEBUG,"can state %s, rxerr %d, txerr %d, txfail %d",NMEA2000.stateStr(canState),canErrors.rx_errors,canErrors.tx_errors,canErrors.tx_failed); - if (canState != Nmea2kTwai::ST_RUNNING){ - if (canState == Nmea2kTwai::ST_BUS_OFF){ + Nmea2kTwai::Status canState=NMEA2000.getStatus(); + logger.logDebug(GwLog::DEBUG,"can state %s, rxerr %d, txerr %d, txfail %d, rxmiss %d, rxoverrun %d", + NMEA2000.stateStr(canState.state), + canState.rx_errors, + canState.tx_errors, + canState.tx_failed, + canState.rx_missed, + canState.rx_overrun); + if (canState.state != Nmea2kTwai::ST_RUNNING){ + if (canState.state == Nmea2kTwai::ST_BUS_OFF){ bool rt=NMEA2000.startRecovery(); logger.logDebug(GwLog::LOG,"start can recovery - result %d",(int)rt); } - if (canState == Nmea2kTwai::ST_STOPPED){ + if (canState.state == Nmea2kTwai::ST_STOPPED){ bool rt=NMEA2000.CANOpen(); logger.logDebug(GwLog::LOG,"restart can driver - result %d",(int)rt); } diff --git a/web/index.html b/web/index.html index 2ecf096..e50eabc 100644 --- a/web/index.html +++ b/web/index.html @@ -58,7 +58,11 @@