From b7a7dad290848d79ec7d6b896435204394de549f Mon Sep 17 00:00:00 2001
From: andreas <andreas@wellenvogel.de>
Date: Sat, 26 Aug 2023 11:06:11 +0200
Subject: [PATCH] better display for bus off condition

---
 lib/nmea2ktwai/Nmea2kTwai.cpp |  1 +
 lib/nmea2ktwai/Nmea2kTwai.h   |  2 ++
 src/main.cpp                  | 15 +++++++++++++--
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/lib/nmea2ktwai/Nmea2kTwai.cpp b/lib/nmea2ktwai/Nmea2kTwai.cpp
index 15dceed..a5f0312 100644
--- a/lib/nmea2ktwai/Nmea2kTwai.cpp
+++ b/lib/nmea2ktwai/Nmea2kTwai.cpp
@@ -157,6 +157,7 @@ Nmea2kTwai::Status Nmea2kTwai::logStatus(){
 }
 
 bool Nmea2kTwai::startRecovery(){
+    lastRecoveryStart=millis();
     esp_err_t rt=twai_driver_uninstall();
     if (rt != ESP_OK){
         logDebug(LOG_ERR,"twai: deinit for recovery failed with %x",(int)rt);
diff --git a/lib/nmea2ktwai/Nmea2kTwai.h b/lib/nmea2ktwai/Nmea2kTwai.h
index f44e4ea..46e9b0c 100644
--- a/lib/nmea2ktwai/Nmea2kTwai.h
+++ b/lib/nmea2ktwai/Nmea2kTwai.h
@@ -25,6 +25,7 @@ class Nmea2kTwai : public tNMEA2000{
             STATE state=ST_ERROR;
         } Status;
         Status getStatus();
+        unsigned long getLastRecoveryStart(){return lastRecoveryStart;}
         void loop();
         static const char * stateStr(const STATE &st);
         virtual bool CANOpen();
@@ -54,6 +55,7 @@ class Nmea2kTwai : public tNMEA2000{
     gpio_num_t RxPin;
     uint32_t txTimeouts=0;
     GwIntervalRunner timers;
+    unsigned long lastRecoveryStart=0;
 };
 
 #endif
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index 07e9042..eba541d 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -112,6 +112,7 @@ GwConfigHandler config(&logger);
 
 #include "Nmea2kTwai.h"
 static const unsigned long CAN_RECOVERY_PERIOD=3000; //ms
+static const unsigned long NMEA2000_HEARTBEAT_INTERVAL=5000;
 class Nmea2kTwaiLog : public Nmea2kTwai{
   private:
     GwLog* logger;
@@ -388,7 +389,17 @@ protected:
     status["fwtype"]= firmwareType;
     status["heap"]=(long)xPortGetFreeHeapSize();
     Nmea2kTwai::Status n2kState=NMEA2000.getStatus();
-    status["n2kstate"]=NMEA2000.stateStr(n2kState.state);
+    Nmea2kTwai::STATE driverState=n2kState.state;
+    if (driverState == Nmea2kTwai::ST_RUNNING){
+      unsigned long lastRec=NMEA2000.getLastRecoveryStart();
+      if (lastRec > 0 && (lastRec+NMEA2000_HEARTBEAT_INTERVAL*2) > millis()){
+        //we still report bus off at least for 2 heartbeat intervals
+        //this avoids always reporting BUS_OFF-RUNNING-BUS_OFF if the bus off condition
+        //remains
+        driverState=Nmea2kTwai::ST_BUS_OFF;
+      }
+    }
+    status["n2kstate"]=NMEA2000.stateStr(driverState);
     status["n2knode"]=NodeAddress;
     //nmea0183Converter->toJson(status);
     countNMEA2KIn.toJson(status);
@@ -802,7 +813,7 @@ void setup() {
   logger.flush();
   NMEA2000.SetMode(tNMEA2000::N2km_ListenAndNode, NodeAddress);
   NMEA2000.SetForwardOwnMessages(false);
-  NMEA2000.SetHeartbeatInterval(5000);
+  NMEA2000.SetHeartbeatInterval(NMEA2000_HEARTBEAT_INTERVAL);
   if (sendOutN2k){
     // Set the information for other bus devices, which messages we support
     unsigned long *pgns=toN2KConverter->handledPgns();