Teseo Location demo for GPSProvider using ST GNSS driver.

Dependencies:   GPS_Provider X_NUCLEO_GNSS1A1

Getting Started with X-NUCLEO-GNSS1A1

This example demonstrates how to use the X-NUCLEO-GNSS1A1 component with one of the STM32 Nucleo-64 platforms and how real time GNSS data received by the Teseo-LIV3F device can be displayed through a serial connection and a serial terminal on a PC. Furthermore the user can run commands enabling three advanced features:

  • Geofencing
  • Odometer
  • Data Logging

Setup

/media/uploads/apalmieri/nucleo-x-nucleo.jpg

Once the antenna has been connected to the SMA female connector of the X-NUCLEO-GNSS1A1 plugged on top of the STM32 Nucleo, a serial connection should be set up between the STM32 Nucleo and the PC with the following parameters:

  • baud rate: 115200
  • data: 8 bit
  • parity: none
  • stop: 1bit
  • flow control: none
  • New-line (Tx/Rx): CR

Serial connection parameters

/media/uploads/apalmieri/serial_setup.png /media/uploads/apalmieri/serial_setup1.png

The user can select among different options to:

  • get in a human readable format information related to the acquired GNSS position (or the satellites in view, the active satellites, and so on)
  • enable feature (geofencing, odometer, data logging)
  • configure a geofence circle
  • require geofence status
  • start/stop feature (odometer, data logging)

Application menu

/media/uploads/apalmieri/teseo_app.png

Revision:
0:7b0a5a01caec
Child:
4:b67349d44157
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/main.cpp	Fri Nov 09 17:10:46 2018 +0000
@@ -0,0 +1,564 @@
+/**
+*******************************************************************************
+* @file    main.cpp
+* @author  AST / Central Lab
+* @version V1.0.0
+* @date    June-2017
+* @brief   Teseo Location Hello World
+*
+*******************************************************************************
+* @attention
+*
+* <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
+*
+* Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*   1. Redistributions of source code must retain the above copyright notice,
+*      this list of conditions and the following disclaimer.
+*   2. Redistributions in binary form must reproduce the above copyright notice,
+*      this list of conditions and the following disclaimer in the documentation
+*      and/or other materials provided with the distribution.
+*   3. Neither the name of STMicroelectronics nor the names of its contributors
+*      may be used to endorse or promote products derived from this software
+*      without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+********************************************************************************
+*/
+
+#include "mbed.h"
+#include "Teseo.h"
+#include "GPSProvider.h"
+
+#include "geofence_config.h"
+
+#define DEBUG_RX_PIN   D0
+#define DEBUG_TX_PIN   D1
+
+/* appliation commands */
+typedef enum AppCmd {
+    APP_CMD_IDLE,           // No special command
+    APP_CMD_HELP,           // Show the supported commands
+    APP_CMD_START,          // Start location
+    APP_CMD_STOP,           // Stop location
+    APP_CMD_GETLASTLOC,     // Get last location
+    APP_CMD_ENGEOFENCE,     // Enable Geofence
+    APP_CMD_CONFGEOFENCE,   // Config Geofence
+    APP_CMD_GEOFENCEREQ,    // Request Geofence status
+    APP_CMD_ENODO,          // Enable Odometer
+    APP_CMD_STARTODO,       // Start Odometer system
+    APP_CMD_STOPODO,        // Stop Odometer system
+    APP_CMD_ENDATALOG,      // Enable Datalog
+    APP_CMD_CONFDATALOG,    // Config Datalog
+    APP_CMD_STARTDATALOG,   // Start Datalog
+    APP_CMD_STOPDATALOG,    // Stop Datalog
+    APP_CMD_ERASEDATALOG,   // Erase Datalog
+    APP_CMD_VERBOSE,        // Enable verbose mode
+    APP_CMD_RESET,          // Debug command, pull reset pin high level
+    APP_CMD_GET_DEVICE_INFO // Get Device Info
+} eAppCmd;
+
+static void _AppShowCmd(void);
+static void _ConsoleRxHandler(void);
+static void _AppCmdProcess(char *pCmd);
+static void _AppShowLastPosition(const GPSProvider::LocationUpdateParams_t *lastLoc);
+static void _AppEnGeofence(const bool isGeofenceSupported);
+static void _AppGeofenceCfg(void);
+static void _AppEnOdometer(const bool isOdometerSupported);
+static void _AppEnDatalogging(const bool isDataloggingSupported);
+static void _AppDatalogCfg(void);
+
+static void _ExecAppCmd(void);
+
+static int sAppCmd = APP_CMD_IDLE;
+static eGeofenceId geofenceId;
+
+Serial serialDebug(DEBUG_TX_PIN, DEBUG_RX_PIN);
+#define TESEO_APP_LOG_INFO(...)   serialDebug.printf(__VA_ARGS__)
+
+#define WARNING_NOT_RUN_MSG TESEO_APP_LOG_INFO("GNSS is not running. Please, type 'start' to make it runnable.\r\n");
+#define WARNING_ALREADY_RUN_MSG TESEO_APP_LOG_INFO("GNSS is already running.\r\n");
+
+static GPSProvider gnss;
+static bool gnssRunning = false;
+static int level = 1;
+
+void
+locationHandler(const GPSProvider::LocationUpdateParams_t *params)
+{
+  if (params->valid) {
+    /* application specific handling of location data; */
+    TESEO_APP_LOG_INFO("locationHandler...\r\n");
+  }
+}
+
+void
+geofenceCfg(int ret_code)
+{
+  TESEO_APP_LOG_INFO("geofenceCfg...\r\n");
+}
+
+void
+geofenceStatus(const GPSProvider::GeofenceStatusParams_t *params, int ret_code)
+{
+  /* application specific handling of geofencing status data; */
+  TESEO_APP_LOG_INFO("geofenceStatus...\r\n");
+}
+
+static void
+_ConsoleRxHandler(void)
+{
+  static char cmd[32] = {0};
+  char        ch;
+
+  while(true) {
+        while (!serialDebug.readable()) {
+            Thread::yield(); // Allow other threads to run
+        }
+        ch = serialDebug.getc();
+        serialDebug.putc(ch);
+        if (ch == '\r') {
+            serialDebug.putc('\n');
+            if (strlen(cmd) > 0) {
+                _AppCmdProcess(cmd);
+                memset(cmd, 0, sizeof(cmd));
+            }
+        } else {
+            cmd[strlen(cmd)] = ch;
+        }
+  }
+}
+
+static
+void
+_ExecAppCmd(void)
+{
+  while (true) {
+    //TESEO_APP_LOG_INFO("main thread!!!\r\n");
+    switch (sAppCmd) {
+    case APP_CMD_HELP:
+      sAppCmd = APP_CMD_IDLE;
+      _AppShowCmd();
+      break;
+
+    case APP_CMD_IDLE:
+      if(gnssRunning) {
+        //TESEO_APP_LOG_INFO("process.\r\n");
+        gnss.process();
+      }
+      break;
+
+    case APP_CMD_START:
+      sAppCmd = APP_CMD_IDLE;
+      if(gnssRunning) {
+        WARNING_ALREADY_RUN_MSG;
+      } else {
+        TESEO_APP_LOG_INFO("start gnss.\r\n");
+        gnss.start();
+        gnssRunning = true;
+      }
+      break;
+    case APP_CMD_STOP:
+      sAppCmd = APP_CMD_IDLE;
+      if(!gnssRunning) {
+        WARNING_NOT_RUN_MSG;
+      } else {
+        TESEO_APP_LOG_INFO("stop gnss.\r\n");
+        gnss.stop();
+        gnssRunning = false;
+      }
+      break;
+    case APP_CMD_RESET:
+      sAppCmd = APP_CMD_IDLE;
+      if(!gnssRunning) {
+        WARNING_NOT_RUN_MSG;
+      } else {
+        TESEO_APP_LOG_INFO("reset on.\r\n");
+        gnss.reset();
+      }
+      break;
+    case APP_CMD_GETLASTLOC:
+      sAppCmd = APP_CMD_IDLE;
+      if(!gnssRunning) {
+        WARNING_NOT_RUN_MSG;
+      } else {
+        TESEO_APP_LOG_INFO("get last loc.\r\n");
+        _AppShowLastPosition(gnss.getLastLocation());
+      }
+      break;
+    case APP_CMD_ENGEOFENCE:
+      sAppCmd = APP_CMD_IDLE;
+      if(!gnssRunning) {
+        WARNING_NOT_RUN_MSG;
+      } else {
+        TESEO_APP_LOG_INFO("enable geofence.\r\n");
+        _AppEnGeofence(gnss.isGeofencingSupported());
+      }
+      break;
+    case APP_CMD_CONFGEOFENCE:
+      sAppCmd = APP_CMD_IDLE;
+      if(!gnssRunning) {
+        WARNING_NOT_RUN_MSG;
+      } else {
+        TESEO_APP_LOG_INFO("config geofence.\r\n");
+        _AppGeofenceCfg();
+      }
+      break;
+    case APP_CMD_GEOFENCEREQ:
+      sAppCmd = APP_CMD_IDLE;
+      if(!gnssRunning) {
+        WARNING_NOT_RUN_MSG;
+      } else {
+        TESEO_APP_LOG_INFO("request geofence status.\r\n");
+        gnss.geofenceReq();
+      }
+      break;
+    case APP_CMD_ENODO:
+      sAppCmd = APP_CMD_IDLE;
+      if(!gnssRunning) {
+        WARNING_NOT_RUN_MSG;
+      } else {
+        TESEO_APP_LOG_INFO("enable odometer.\r\n");
+        _AppEnOdometer(gnss.isOdometerSupported());
+      }
+      break;
+    case APP_CMD_STARTODO:
+      sAppCmd = APP_CMD_IDLE;
+      if(!gnssRunning) {
+        WARNING_NOT_RUN_MSG;
+      } else {
+        TESEO_APP_LOG_INFO("start odo subystem.\r\n");
+        gnss.startOdo(1);
+      }
+      break;
+    case APP_CMD_STOPODO:
+      sAppCmd = APP_CMD_IDLE;
+      if(!gnssRunning) {
+        WARNING_NOT_RUN_MSG;
+      } else {
+        TESEO_APP_LOG_INFO("stop odo subystem.\r\n");
+        gnss.stopOdo();
+      }
+      break;
+    case APP_CMD_ENDATALOG:
+      sAppCmd = APP_CMD_IDLE;
+      if(!gnssRunning) {
+        WARNING_NOT_RUN_MSG;
+      } else {
+        TESEO_APP_LOG_INFO("enable datalog.\r\n");
+        _AppEnDatalogging(gnss.isDataloggingSupported());
+      }
+      break;
+    case APP_CMD_CONFDATALOG:
+      sAppCmd = APP_CMD_IDLE;
+      if(!gnssRunning) {
+        WARNING_NOT_RUN_MSG;
+      } else {
+        TESEO_APP_LOG_INFO("config datalog.\r\n");
+        _AppDatalogCfg();
+      }
+      break;
+    case APP_CMD_STARTDATALOG:
+      sAppCmd = APP_CMD_IDLE;
+      if(!gnssRunning) {
+        WARNING_NOT_RUN_MSG;
+      } else {
+        TESEO_APP_LOG_INFO("start datalog.\r\n");
+        gnss.startDatalog();
+      }
+      break;
+    case APP_CMD_STOPDATALOG:
+      sAppCmd = APP_CMD_IDLE;
+      if(!gnssRunning) {
+        WARNING_NOT_RUN_MSG;
+      } else {
+        TESEO_APP_LOG_INFO("stop datalog.\r\n");
+        gnss.stopDatalog();
+      }
+      break;
+    case APP_CMD_ERASEDATALOG:
+      sAppCmd = APP_CMD_IDLE;
+      if(!gnssRunning) {
+        WARNING_NOT_RUN_MSG;
+      } else {
+        TESEO_APP_LOG_INFO("erase datalog.\r\n");
+        gnss.eraseDatalog();
+      }
+      break;
+    case APP_CMD_VERBOSE:
+      sAppCmd = APP_CMD_IDLE;
+      if(!gnssRunning) {
+        WARNING_NOT_RUN_MSG;
+      } else {
+        TESEO_APP_LOG_INFO("set verbose mode.\r\n");
+        gnss.setVerboseMode(level);
+      }
+      break;
+    case APP_CMD_GET_DEVICE_INFO:
+      sAppCmd = APP_CMD_IDLE;
+      if(!gnssRunning) {
+        WARNING_NOT_RUN_MSG;
+      } else {
+        TESEO_APP_LOG_INFO("get device info.\r\n");
+        if(gnss.haveDeviceInfo()) {
+          TESEO_APP_LOG_INFO(gnss.getDeviceInfo());
+        }
+        TESEO_APP_LOG_INFO("\r\n");
+      }
+      break;
+    }
+    Thread::yield(); // Allow other threads to run
+  }
+}
+
+int main() {
+  Thread consoleThread;
+  Thread cmdThread;
+  
+  consoleThread.set_priority(osPriorityIdle);
+  cmdThread.set_priority(osPriorityIdle);
+
+  serialDebug.format(8, Serial::None, 1);
+  serialDebug.baud(115200);
+  consoleThread.start(_ConsoleRxHandler);
+  
+  gnss.reset();
+  gnss.onLocationUpdate(locationHandler);
+  TESEO_APP_LOG_INFO("Success to new GNSS.\r\n");
+
+  _AppShowCmd();
+  cmdThread.start(_ExecAppCmd);
+
+  while(1) {
+    Thread::yield();
+  }
+  
+}
+
+static void
+_AppShowLastPosition(const GPSProvider::LocationUpdateParams_t *lastLoc)
+{
+  char msg[256];
+  GPSProvider::LocationUpdateParams_t lastLocation = *lastLoc;
+
+  if(lastLocation.valid == true) {
+    sprintf(msg,"Latitude:\t\t[ %.0f' %d'' ]\n\r",
+            (lastLocation.lat - ((int)lastLocation.lat % 100)) / 100, 
+            ((int)lastLocation.lat % 100));          
+    TESEO_APP_LOG_INFO(msg);
+    
+    sprintf(msg,"Longitude:\t\t[ %.0f' %d'' ]\n\r",
+            (lastLocation.lon - ((int)lastLocation.lon % 100)) / 100, 
+            ((int)lastLocation.lon % 100));          
+    TESEO_APP_LOG_INFO(msg);
+    
+    sprintf(msg,"Altitude:\t\t[ %.2f ]\n\r",
+            lastLocation.altitude);
+    TESEO_APP_LOG_INFO(msg);
+    
+    sprintf(msg,"Satellites locked:\t[ %d ]\n\r",
+            lastLocation.numGPSSVs);
+    TESEO_APP_LOG_INFO(msg);
+    
+    sprintf(msg, "UTC:\t\t\t[ %d ]\n\r",
+            (int)lastLocation.utcTime);
+    TESEO_APP_LOG_INFO(msg);
+    
+  } else {
+    sprintf(msg, "Last position wasn't valid.\n\n\r");
+    TESEO_APP_LOG_INFO(msg);
+  }
+}
+
+static void
+_AppEnGeofence(const bool isGeofenceSupported)
+{
+  if(isGeofenceSupported) {
+    gps_provider_error_t ret = gnss.enableGeofence();
+    if(ret == GPS_ERROR_NONE) {
+      TESEO_APP_LOG_INFO("Enabling Geofencing subsystem...\n\r");
+    }
+  } else {
+    TESEO_APP_LOG_INFO("Geofencing is not supported!\n\r");
+  }
+
+}
+
+static void
+_AppGeofenceCfg(void)
+{
+  GPSGeofence gf;
+
+  switch (geofenceId) {
+  case LecceId:
+    gf.setGeofenceCircle(STLecce);
+    break;
+  case CataniaId:
+    gf.setGeofenceCircle(Catania);
+    break;
+  }
+  /*
+  GPSGeofence::GeofenceCircle_t c = gf.getGeofenceCircle();
+  printf("_AppGeofenceCfg id=%d\r\n", c.id);
+  printf("_AppGeofenceCfg en=%d\r\n", c.enabled);
+  printf("_AppGeofenceCfg tol=%d\r\n", c.tolerance);
+  printf("_AppGeofenceCfg lat=%.2f\r\n", c.lat);
+  printf("_AppGeofenceCfg lon=%.2f\r\n", c.lon);
+  printf("_AppGeofenceCfg radius=%.2f\r\n", c.radius);
+  */
+  
+  GPSGeofence *geofenceTable[] = {&gf};
+
+  gnss.onGeofenceCfgMessage(geofenceCfg);
+  gnss.onGeofenceStatusMessage(geofenceStatus);
+  gps_provider_error_t ret = gnss.configGeofences(geofenceTable, sizeof(geofenceTable)/sizeof(GPSGeofence *));
+  if(ret == GPS_ERROR_NONE) {
+    TESEO_APP_LOG_INFO("Configuring Geofence circles...\n\r");
+  }
+
+}
+
+static void
+_AppEnOdometer(const bool isOdometerSupported)
+{
+  if(isOdometerSupported) {
+    gps_provider_error_t ret = gnss.enableOdo();
+    if(ret == GPS_ERROR_NONE) {
+      TESEO_APP_LOG_INFO("Enabling Odometer subsystem...\n\r");
+    }
+  } else {
+    TESEO_APP_LOG_INFO("Odometer is not supported!\n\r");
+  }
+
+}
+
+static void
+_AppEnDatalogging(const bool isDataloggingSupported)
+{
+  if(isDataloggingSupported) {
+    gps_provider_error_t ret = gnss.enableDatalog();
+    if(ret == GPS_ERROR_NONE) {
+      TESEO_APP_LOG_INFO("Enabling Datalog subsystem...\n\r");
+    }
+  } else {
+    TESEO_APP_LOG_INFO("Datalog is not supported!\n\r");
+  }
+
+}
+
+static void
+_AppDatalogCfg(void)
+{
+  bool          enableBufferFullAlarm = false;
+  bool          enableCircularBuffer = true;
+  unsigned      minRate = 5;
+  unsigned      minSpeed = 0;
+  unsigned      minPosition = 0;
+  int           logMask = 1;
+
+  GPSDatalog dl(enableBufferFullAlarm,
+                enableCircularBuffer,
+                minRate,
+                minSpeed,
+                minPosition,
+                logMask);
+
+  gps_provider_error_t ret = gnss.configDatalog(&dl);
+  if(ret == GPS_ERROR_NONE) {
+    TESEO_APP_LOG_INFO("Configuring Datalog...\n\r");
+  }
+}
+
+static void
+_AppShowCmd(void)
+{
+    TESEO_APP_LOG_INFO("Location commands:\r\n");
+    TESEO_APP_LOG_INFO("    help         - help to show supported commands\r\n");
+    TESEO_APP_LOG_INFO("    start        - begin location app\r\n");
+    TESEO_APP_LOG_INFO("    stop         - end location app\r\n");
+    TESEO_APP_LOG_INFO("    getlastloc   - get last location\r\n");
+    TESEO_APP_LOG_INFO("    en-geo       - enable Geofence\r\n");
+    TESEO_APP_LOG_INFO("    geo-c        - config Geofence [c=l Lecce, c=t Catania]\r\n");
+    TESEO_APP_LOG_INFO("    req-geo      - request Geofence status\r\n");
+    TESEO_APP_LOG_INFO("    en-odo       - enable Odoemter\r\n");
+    TESEO_APP_LOG_INFO("    start-odo    - start Ododmeter [demo distance 1m]\r\n");
+    TESEO_APP_LOG_INFO("    stop-odo     - stop Ododmeter\r\n");
+    TESEO_APP_LOG_INFO("    en-datalog   - enable Datalog\r\n");
+    TESEO_APP_LOG_INFO("    cfg-dl       - config Datalog\r\n");
+    TESEO_APP_LOG_INFO("    start-dl     - start Datalog\r\n");
+    TESEO_APP_LOG_INFO("    stop-dl      - stop Datalog\r\n");
+    TESEO_APP_LOG_INFO("    erase-dl     - erase Datalog\r\n");
+    TESEO_APP_LOG_INFO("    verbose-l    - nmea msg verbose mode [l=1 normal, l=2 debug]\r\n");
+    TESEO_APP_LOG_INFO("    reset        - reset GNSS\r\n");
+    TESEO_APP_LOG_INFO("    getdevinfo   - get device info\r\n");
+}
+
+static void
+_AppCmdProcess(char *pCmd)
+{
+    if (strcmp(pCmd, "help") == 0) {
+        sAppCmd = APP_CMD_HELP;
+    } else if (strcmp(pCmd, "start") == 0) {
+        sAppCmd = APP_CMD_START;
+    } else if (strcmp(pCmd, "stop") == 0) {
+        sAppCmd = APP_CMD_STOP;
+    } else if (strcmp(pCmd, "getlastloc") == 0) {
+        sAppCmd = APP_CMD_GETLASTLOC;
+    } else if (strcmp(pCmd, "en-geo") == 0) {
+        sAppCmd = APP_CMD_ENGEOFENCE;
+    } else if (strcmp(pCmd, "geo-l") == 0) {
+        geofenceId = LecceId;
+        sAppCmd = APP_CMD_CONFGEOFENCE;
+    } else if (strcmp(pCmd, "geo-t") == 0) {
+        geofenceId = CataniaId;
+        sAppCmd = APP_CMD_CONFGEOFENCE;
+    } else if (strcmp(pCmd, "req-geo") == 0) {
+        sAppCmd = APP_CMD_GEOFENCEREQ;
+    } else if (strcmp(pCmd, "en-odo") == 0) {
+        sAppCmd = APP_CMD_ENODO;
+    } else if (strcmp(pCmd, "start-odo") == 0) {
+        sAppCmd = APP_CMD_STARTODO;
+    } else if (strcmp(pCmd, "stop-odo") == 0) {
+        sAppCmd = APP_CMD_STOPODO;
+    } else if (strcmp(pCmd, "en-datalog") == 0) {
+        sAppCmd = APP_CMD_ENDATALOG;
+    } else if (strcmp(pCmd, "cfg-dl") == 0) {
+        sAppCmd = APP_CMD_CONFDATALOG;
+    } else if (strcmp(pCmd, "start-dl") == 0) {
+        sAppCmd = APP_CMD_STARTDATALOG;
+    } else if (strcmp(pCmd, "stop-dl") == 0) {
+        sAppCmd = APP_CMD_STOPDATALOG;
+    } else if (strcmp(pCmd, "erase-dl") == 0) {
+        sAppCmd = APP_CMD_ERASEDATALOG;
+    } else if (strcmp(pCmd, "verbose-1") == 0) {
+        level = 1;
+        sAppCmd = APP_CMD_VERBOSE;
+    } else if (strcmp(pCmd, "verbose-2") == 0) {
+        level = 2;
+        sAppCmd = APP_CMD_VERBOSE;
+    } else if (strcmp(pCmd, "reset") == 0) {
+        sAppCmd = APP_CMD_RESET;
+    } else if (strcmp(pCmd, "getdevinfo") == 0) {
+        sAppCmd = APP_CMD_GET_DEVICE_INFO;
+    } else {
+        TESEO_APP_LOG_INFO("\r\nUnknown command %s\r\n", pCmd);
+    }
+
+    TESEO_APP_LOG_INFO("\r\n");
+}