text: /*
   * ProductDebug.cpp
   *
   *  Created on: 14.06.2016
   *      Author: nid
   */
  
  #include "ProductDebug.h"
  
  #include <Arduino.h>
  #include <Timer.h>
  #include <SerialCommand.h>
  #include <DbgCliNode.h>
  #include <DbgCliTopic.h>
  #include <DbgCliCommand.h>
  #include <DbgTraceContext.h>
  #include <DbgTracePort.h>
  #include <DbgTraceLevel.h>
  #include <DbgPrintConsole.h>
  #include <DbgTraceOut.h>
  #include <RamUtils.h>
  
  //-----------------------------------------------------------------------------
  // Free Heap Logger
  //-----------------------------------------------------------------------------
  const unsigned long c_freeHeapLogIntervalMillis = 10000;
  
  class FreeHeapLogTimerAdapter : public TimerAdapter
  {
  private:
    DbgTrace_Port* m_trPort;
  public:
    FreeHeapLogTimerAdapter()
    : m_trPort(new DbgTrace_Port("heap", DbgTrace_Level::info))
    { }
  
    void timeExpired()
    {
  #ifdef ESP8266
      TR_PRINT_LONG(m_trPort, DbgTrace_Level::debug, system_get_free_heap_size());
  #else
      TR_PRINT_LONG(m_trPort, DbgTrace_Level::debug, RamUtils::getFreeRam());
  #endif
    }
  };
  
  //-----------------------------------------------------------------------------
  
  extern SerialCommand* sCmd;
  
  void setupDebugEnv()
  {
    //-----------------------------------------------------------------------------
    // Serial Command Object for Debug CLI
    //-----------------------------------------------------------------------------
    Serial.begin(115200);
    sCmd = new SerialCommand();
    DbgCli_Node::AssignRootNode(new DbgCli_Topic(0, "dbg", "Wiring Controller Debug CLI Root Node."));
  
    // Setup callbacks for SerialCommand commands
    if (0 != sCmd)
    {
      sCmd->addCommand("dbg", dbgCliExecute);
      sCmd->addCommand("hello", sayHello);        // Echos the string argument back
      sCmd->setDefaultHandler(unrecognized);      // Handler for command that isn't matched  (says "What?")
    }
  
    //---------------------------------------------------------------------------
    // Debug Trace
    //---------------------------------------------------------------------------
    new DbgTrace_Context(new DbgCli_Topic(DbgCli_Node::RootNode(), "tr", "Modify debug trace"));
    new DbgTrace_Out(DbgTrace_Context::getContext(), "trConOut", new DbgPrint_Console());
  
    //-----------------------------------------------------------------------------
    // Free Heap Logger
    //-----------------------------------------------------------------------------
    new Timer(new FreeHeapLogTimerAdapter(), Timer::IS_RECURRING, c_freeHeapLogIntervalMillis);
  
    Serial.println();
    Serial.println("---------------------------------------------");
    Serial.println("Hello from Wiring Controller!");
    Serial.println("---------------------------------------------");
    Serial.println();
  }
  
  void dbgCliExecute()
  {
    if ((0 != sCmd) && (0 != DbgCli_Node::RootNode()))
    {
      const unsigned int firstArgToHandle = 1;
      const unsigned int maxArgCnt = 10;
      char* args[maxArgCnt];
      char* arg = const_cast<char*>("dbg");
      unsigned int arg_cnt = 0;
      while ((maxArgCnt > arg_cnt) && (0 != arg))
      {
        args[arg_cnt] = arg;
        arg = sCmd->next();
        arg_cnt++;
      }
      DbgCli_Node::RootNode()->execute(static_cast<unsigned int>(arg_cnt), const_cast<const char**>(args), firstArgToHandle);
    }
  }
  
  void sayHello()
  {
    char *arg;
    if (0 != sCmd)
    {
      arg = sCmd->next();    // Get the next argument from the SerialCommand object buffer
    }
    else
    {
      arg = const_cast<char*>("");;
    }
    if (arg != NULL)         // As long as it exists, take it
    {
      Serial.print("Hello ");
      Serial.println(arg);
    }
    else
    {
      Serial.println("Hello, whoever you are");
    }
  }
  
  // This is the default handler, and gets called when no other command matches.
  void unrecognized(const char *command)
  {
    Serial.println("What?");
  }
  