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

Committer:
apalmieri
Date:
Fri Nov 09 17:10:46 2018 +0000
Revision:
0:7b0a5a01caec
Child:
4:b67349d44157
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
apalmieri 0:7b0a5a01caec 1 /**
apalmieri 0:7b0a5a01caec 2 *******************************************************************************
apalmieri 0:7b0a5a01caec 3 * @file main.cpp
apalmieri 0:7b0a5a01caec 4 * @author AST / Central Lab
apalmieri 0:7b0a5a01caec 5 * @version V1.0.0
apalmieri 0:7b0a5a01caec 6 * @date June-2017
apalmieri 0:7b0a5a01caec 7 * @brief Teseo Location Hello World
apalmieri 0:7b0a5a01caec 8 *
apalmieri 0:7b0a5a01caec 9 *******************************************************************************
apalmieri 0:7b0a5a01caec 10 * @attention
apalmieri 0:7b0a5a01caec 11 *
apalmieri 0:7b0a5a01caec 12 * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
apalmieri 0:7b0a5a01caec 13 *
apalmieri 0:7b0a5a01caec 14 * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
apalmieri 0:7b0a5a01caec 15 * You may not use this file except in compliance with the License.
apalmieri 0:7b0a5a01caec 16 * You may obtain a copy of the License at:
apalmieri 0:7b0a5a01caec 17 *
apalmieri 0:7b0a5a01caec 18 * http://www.st.com/software_license_agreement_liberty_v2
apalmieri 0:7b0a5a01caec 19 *
apalmieri 0:7b0a5a01caec 20 * Redistribution and use in source and binary forms, with or without modification,
apalmieri 0:7b0a5a01caec 21 * are permitted provided that the following conditions are met:
apalmieri 0:7b0a5a01caec 22 * 1. Redistributions of source code must retain the above copyright notice,
apalmieri 0:7b0a5a01caec 23 * this list of conditions and the following disclaimer.
apalmieri 0:7b0a5a01caec 24 * 2. Redistributions in binary form must reproduce the above copyright notice,
apalmieri 0:7b0a5a01caec 25 * this list of conditions and the following disclaimer in the documentation
apalmieri 0:7b0a5a01caec 26 * and/or other materials provided with the distribution.
apalmieri 0:7b0a5a01caec 27 * 3. Neither the name of STMicroelectronics nor the names of its contributors
apalmieri 0:7b0a5a01caec 28 * may be used to endorse or promote products derived from this software
apalmieri 0:7b0a5a01caec 29 * without specific prior written permission.
apalmieri 0:7b0a5a01caec 30 *
apalmieri 0:7b0a5a01caec 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
apalmieri 0:7b0a5a01caec 32 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
apalmieri 0:7b0a5a01caec 33 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
apalmieri 0:7b0a5a01caec 34 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
apalmieri 0:7b0a5a01caec 35 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
apalmieri 0:7b0a5a01caec 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
apalmieri 0:7b0a5a01caec 37 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
apalmieri 0:7b0a5a01caec 38 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
apalmieri 0:7b0a5a01caec 39 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
apalmieri 0:7b0a5a01caec 40 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
apalmieri 0:7b0a5a01caec 41 *
apalmieri 0:7b0a5a01caec 42 ********************************************************************************
apalmieri 0:7b0a5a01caec 43 */
apalmieri 0:7b0a5a01caec 44
apalmieri 0:7b0a5a01caec 45 #include "mbed.h"
apalmieri 0:7b0a5a01caec 46 #include "Teseo.h"
apalmieri 0:7b0a5a01caec 47 #include "GPSProvider.h"
apalmieri 0:7b0a5a01caec 48
apalmieri 0:7b0a5a01caec 49 #include "geofence_config.h"
apalmieri 0:7b0a5a01caec 50
apalmieri 0:7b0a5a01caec 51 #define DEBUG_RX_PIN D0
apalmieri 0:7b0a5a01caec 52 #define DEBUG_TX_PIN D1
apalmieri 0:7b0a5a01caec 53
apalmieri 0:7b0a5a01caec 54 /* appliation commands */
apalmieri 0:7b0a5a01caec 55 typedef enum AppCmd {
apalmieri 0:7b0a5a01caec 56 APP_CMD_IDLE, // No special command
apalmieri 0:7b0a5a01caec 57 APP_CMD_HELP, // Show the supported commands
apalmieri 0:7b0a5a01caec 58 APP_CMD_START, // Start location
apalmieri 0:7b0a5a01caec 59 APP_CMD_STOP, // Stop location
apalmieri 0:7b0a5a01caec 60 APP_CMD_GETLASTLOC, // Get last location
apalmieri 0:7b0a5a01caec 61 APP_CMD_ENGEOFENCE, // Enable Geofence
apalmieri 0:7b0a5a01caec 62 APP_CMD_CONFGEOFENCE, // Config Geofence
apalmieri 0:7b0a5a01caec 63 APP_CMD_GEOFENCEREQ, // Request Geofence status
apalmieri 0:7b0a5a01caec 64 APP_CMD_ENODO, // Enable Odometer
apalmieri 0:7b0a5a01caec 65 APP_CMD_STARTODO, // Start Odometer system
apalmieri 0:7b0a5a01caec 66 APP_CMD_STOPODO, // Stop Odometer system
apalmieri 0:7b0a5a01caec 67 APP_CMD_ENDATALOG, // Enable Datalog
apalmieri 0:7b0a5a01caec 68 APP_CMD_CONFDATALOG, // Config Datalog
apalmieri 0:7b0a5a01caec 69 APP_CMD_STARTDATALOG, // Start Datalog
apalmieri 0:7b0a5a01caec 70 APP_CMD_STOPDATALOG, // Stop Datalog
apalmieri 0:7b0a5a01caec 71 APP_CMD_ERASEDATALOG, // Erase Datalog
apalmieri 0:7b0a5a01caec 72 APP_CMD_VERBOSE, // Enable verbose mode
apalmieri 0:7b0a5a01caec 73 APP_CMD_RESET, // Debug command, pull reset pin high level
apalmieri 0:7b0a5a01caec 74 APP_CMD_GET_DEVICE_INFO // Get Device Info
apalmieri 0:7b0a5a01caec 75 } eAppCmd;
apalmieri 0:7b0a5a01caec 76
apalmieri 0:7b0a5a01caec 77 static void _AppShowCmd(void);
apalmieri 0:7b0a5a01caec 78 static void _ConsoleRxHandler(void);
apalmieri 0:7b0a5a01caec 79 static void _AppCmdProcess(char *pCmd);
apalmieri 0:7b0a5a01caec 80 static void _AppShowLastPosition(const GPSProvider::LocationUpdateParams_t *lastLoc);
apalmieri 0:7b0a5a01caec 81 static void _AppEnGeofence(const bool isGeofenceSupported);
apalmieri 0:7b0a5a01caec 82 static void _AppGeofenceCfg(void);
apalmieri 0:7b0a5a01caec 83 static void _AppEnOdometer(const bool isOdometerSupported);
apalmieri 0:7b0a5a01caec 84 static void _AppEnDatalogging(const bool isDataloggingSupported);
apalmieri 0:7b0a5a01caec 85 static void _AppDatalogCfg(void);
apalmieri 0:7b0a5a01caec 86
apalmieri 0:7b0a5a01caec 87 static void _ExecAppCmd(void);
apalmieri 0:7b0a5a01caec 88
apalmieri 0:7b0a5a01caec 89 static int sAppCmd = APP_CMD_IDLE;
apalmieri 0:7b0a5a01caec 90 static eGeofenceId geofenceId;
apalmieri 0:7b0a5a01caec 91
apalmieri 0:7b0a5a01caec 92 Serial serialDebug(DEBUG_TX_PIN, DEBUG_RX_PIN);
apalmieri 0:7b0a5a01caec 93 #define TESEO_APP_LOG_INFO(...) serialDebug.printf(__VA_ARGS__)
apalmieri 0:7b0a5a01caec 94
apalmieri 0:7b0a5a01caec 95 #define WARNING_NOT_RUN_MSG TESEO_APP_LOG_INFO("GNSS is not running. Please, type 'start' to make it runnable.\r\n");
apalmieri 0:7b0a5a01caec 96 #define WARNING_ALREADY_RUN_MSG TESEO_APP_LOG_INFO("GNSS is already running.\r\n");
apalmieri 0:7b0a5a01caec 97
apalmieri 0:7b0a5a01caec 98 static GPSProvider gnss;
apalmieri 0:7b0a5a01caec 99 static bool gnssRunning = false;
apalmieri 0:7b0a5a01caec 100 static int level = 1;
apalmieri 0:7b0a5a01caec 101
apalmieri 0:7b0a5a01caec 102 void
apalmieri 0:7b0a5a01caec 103 locationHandler(const GPSProvider::LocationUpdateParams_t *params)
apalmieri 0:7b0a5a01caec 104 {
apalmieri 0:7b0a5a01caec 105 if (params->valid) {
apalmieri 0:7b0a5a01caec 106 /* application specific handling of location data; */
apalmieri 0:7b0a5a01caec 107 TESEO_APP_LOG_INFO("locationHandler...\r\n");
apalmieri 0:7b0a5a01caec 108 }
apalmieri 0:7b0a5a01caec 109 }
apalmieri 0:7b0a5a01caec 110
apalmieri 0:7b0a5a01caec 111 void
apalmieri 0:7b0a5a01caec 112 geofenceCfg(int ret_code)
apalmieri 0:7b0a5a01caec 113 {
apalmieri 0:7b0a5a01caec 114 TESEO_APP_LOG_INFO("geofenceCfg...\r\n");
apalmieri 0:7b0a5a01caec 115 }
apalmieri 0:7b0a5a01caec 116
apalmieri 0:7b0a5a01caec 117 void
apalmieri 0:7b0a5a01caec 118 geofenceStatus(const GPSProvider::GeofenceStatusParams_t *params, int ret_code)
apalmieri 0:7b0a5a01caec 119 {
apalmieri 0:7b0a5a01caec 120 /* application specific handling of geofencing status data; */
apalmieri 0:7b0a5a01caec 121 TESEO_APP_LOG_INFO("geofenceStatus...\r\n");
apalmieri 0:7b0a5a01caec 122 }
apalmieri 0:7b0a5a01caec 123
apalmieri 0:7b0a5a01caec 124 static void
apalmieri 0:7b0a5a01caec 125 _ConsoleRxHandler(void)
apalmieri 0:7b0a5a01caec 126 {
apalmieri 0:7b0a5a01caec 127 static char cmd[32] = {0};
apalmieri 0:7b0a5a01caec 128 char ch;
apalmieri 0:7b0a5a01caec 129
apalmieri 0:7b0a5a01caec 130 while(true) {
apalmieri 0:7b0a5a01caec 131 while (!serialDebug.readable()) {
apalmieri 0:7b0a5a01caec 132 Thread::yield(); // Allow other threads to run
apalmieri 0:7b0a5a01caec 133 }
apalmieri 0:7b0a5a01caec 134 ch = serialDebug.getc();
apalmieri 0:7b0a5a01caec 135 serialDebug.putc(ch);
apalmieri 0:7b0a5a01caec 136 if (ch == '\r') {
apalmieri 0:7b0a5a01caec 137 serialDebug.putc('\n');
apalmieri 0:7b0a5a01caec 138 if (strlen(cmd) > 0) {
apalmieri 0:7b0a5a01caec 139 _AppCmdProcess(cmd);
apalmieri 0:7b0a5a01caec 140 memset(cmd, 0, sizeof(cmd));
apalmieri 0:7b0a5a01caec 141 }
apalmieri 0:7b0a5a01caec 142 } else {
apalmieri 0:7b0a5a01caec 143 cmd[strlen(cmd)] = ch;
apalmieri 0:7b0a5a01caec 144 }
apalmieri 0:7b0a5a01caec 145 }
apalmieri 0:7b0a5a01caec 146 }
apalmieri 0:7b0a5a01caec 147
apalmieri 0:7b0a5a01caec 148 static
apalmieri 0:7b0a5a01caec 149 void
apalmieri 0:7b0a5a01caec 150 _ExecAppCmd(void)
apalmieri 0:7b0a5a01caec 151 {
apalmieri 0:7b0a5a01caec 152 while (true) {
apalmieri 0:7b0a5a01caec 153 //TESEO_APP_LOG_INFO("main thread!!!\r\n");
apalmieri 0:7b0a5a01caec 154 switch (sAppCmd) {
apalmieri 0:7b0a5a01caec 155 case APP_CMD_HELP:
apalmieri 0:7b0a5a01caec 156 sAppCmd = APP_CMD_IDLE;
apalmieri 0:7b0a5a01caec 157 _AppShowCmd();
apalmieri 0:7b0a5a01caec 158 break;
apalmieri 0:7b0a5a01caec 159
apalmieri 0:7b0a5a01caec 160 case APP_CMD_IDLE:
apalmieri 0:7b0a5a01caec 161 if(gnssRunning) {
apalmieri 0:7b0a5a01caec 162 //TESEO_APP_LOG_INFO("process.\r\n");
apalmieri 0:7b0a5a01caec 163 gnss.process();
apalmieri 0:7b0a5a01caec 164 }
apalmieri 0:7b0a5a01caec 165 break;
apalmieri 0:7b0a5a01caec 166
apalmieri 0:7b0a5a01caec 167 case APP_CMD_START:
apalmieri 0:7b0a5a01caec 168 sAppCmd = APP_CMD_IDLE;
apalmieri 0:7b0a5a01caec 169 if(gnssRunning) {
apalmieri 0:7b0a5a01caec 170 WARNING_ALREADY_RUN_MSG;
apalmieri 0:7b0a5a01caec 171 } else {
apalmieri 0:7b0a5a01caec 172 TESEO_APP_LOG_INFO("start gnss.\r\n");
apalmieri 0:7b0a5a01caec 173 gnss.start();
apalmieri 0:7b0a5a01caec 174 gnssRunning = true;
apalmieri 0:7b0a5a01caec 175 }
apalmieri 0:7b0a5a01caec 176 break;
apalmieri 0:7b0a5a01caec 177 case APP_CMD_STOP:
apalmieri 0:7b0a5a01caec 178 sAppCmd = APP_CMD_IDLE;
apalmieri 0:7b0a5a01caec 179 if(!gnssRunning) {
apalmieri 0:7b0a5a01caec 180 WARNING_NOT_RUN_MSG;
apalmieri 0:7b0a5a01caec 181 } else {
apalmieri 0:7b0a5a01caec 182 TESEO_APP_LOG_INFO("stop gnss.\r\n");
apalmieri 0:7b0a5a01caec 183 gnss.stop();
apalmieri 0:7b0a5a01caec 184 gnssRunning = false;
apalmieri 0:7b0a5a01caec 185 }
apalmieri 0:7b0a5a01caec 186 break;
apalmieri 0:7b0a5a01caec 187 case APP_CMD_RESET:
apalmieri 0:7b0a5a01caec 188 sAppCmd = APP_CMD_IDLE;
apalmieri 0:7b0a5a01caec 189 if(!gnssRunning) {
apalmieri 0:7b0a5a01caec 190 WARNING_NOT_RUN_MSG;
apalmieri 0:7b0a5a01caec 191 } else {
apalmieri 0:7b0a5a01caec 192 TESEO_APP_LOG_INFO("reset on.\r\n");
apalmieri 0:7b0a5a01caec 193 gnss.reset();
apalmieri 0:7b0a5a01caec 194 }
apalmieri 0:7b0a5a01caec 195 break;
apalmieri 0:7b0a5a01caec 196 case APP_CMD_GETLASTLOC:
apalmieri 0:7b0a5a01caec 197 sAppCmd = APP_CMD_IDLE;
apalmieri 0:7b0a5a01caec 198 if(!gnssRunning) {
apalmieri 0:7b0a5a01caec 199 WARNING_NOT_RUN_MSG;
apalmieri 0:7b0a5a01caec 200 } else {
apalmieri 0:7b0a5a01caec 201 TESEO_APP_LOG_INFO("get last loc.\r\n");
apalmieri 0:7b0a5a01caec 202 _AppShowLastPosition(gnss.getLastLocation());
apalmieri 0:7b0a5a01caec 203 }
apalmieri 0:7b0a5a01caec 204 break;
apalmieri 0:7b0a5a01caec 205 case APP_CMD_ENGEOFENCE:
apalmieri 0:7b0a5a01caec 206 sAppCmd = APP_CMD_IDLE;
apalmieri 0:7b0a5a01caec 207 if(!gnssRunning) {
apalmieri 0:7b0a5a01caec 208 WARNING_NOT_RUN_MSG;
apalmieri 0:7b0a5a01caec 209 } else {
apalmieri 0:7b0a5a01caec 210 TESEO_APP_LOG_INFO("enable geofence.\r\n");
apalmieri 0:7b0a5a01caec 211 _AppEnGeofence(gnss.isGeofencingSupported());
apalmieri 0:7b0a5a01caec 212 }
apalmieri 0:7b0a5a01caec 213 break;
apalmieri 0:7b0a5a01caec 214 case APP_CMD_CONFGEOFENCE:
apalmieri 0:7b0a5a01caec 215 sAppCmd = APP_CMD_IDLE;
apalmieri 0:7b0a5a01caec 216 if(!gnssRunning) {
apalmieri 0:7b0a5a01caec 217 WARNING_NOT_RUN_MSG;
apalmieri 0:7b0a5a01caec 218 } else {
apalmieri 0:7b0a5a01caec 219 TESEO_APP_LOG_INFO("config geofence.\r\n");
apalmieri 0:7b0a5a01caec 220 _AppGeofenceCfg();
apalmieri 0:7b0a5a01caec 221 }
apalmieri 0:7b0a5a01caec 222 break;
apalmieri 0:7b0a5a01caec 223 case APP_CMD_GEOFENCEREQ:
apalmieri 0:7b0a5a01caec 224 sAppCmd = APP_CMD_IDLE;
apalmieri 0:7b0a5a01caec 225 if(!gnssRunning) {
apalmieri 0:7b0a5a01caec 226 WARNING_NOT_RUN_MSG;
apalmieri 0:7b0a5a01caec 227 } else {
apalmieri 0:7b0a5a01caec 228 TESEO_APP_LOG_INFO("request geofence status.\r\n");
apalmieri 0:7b0a5a01caec 229 gnss.geofenceReq();
apalmieri 0:7b0a5a01caec 230 }
apalmieri 0:7b0a5a01caec 231 break;
apalmieri 0:7b0a5a01caec 232 case APP_CMD_ENODO:
apalmieri 0:7b0a5a01caec 233 sAppCmd = APP_CMD_IDLE;
apalmieri 0:7b0a5a01caec 234 if(!gnssRunning) {
apalmieri 0:7b0a5a01caec 235 WARNING_NOT_RUN_MSG;
apalmieri 0:7b0a5a01caec 236 } else {
apalmieri 0:7b0a5a01caec 237 TESEO_APP_LOG_INFO("enable odometer.\r\n");
apalmieri 0:7b0a5a01caec 238 _AppEnOdometer(gnss.isOdometerSupported());
apalmieri 0:7b0a5a01caec 239 }
apalmieri 0:7b0a5a01caec 240 break;
apalmieri 0:7b0a5a01caec 241 case APP_CMD_STARTODO:
apalmieri 0:7b0a5a01caec 242 sAppCmd = APP_CMD_IDLE;
apalmieri 0:7b0a5a01caec 243 if(!gnssRunning) {
apalmieri 0:7b0a5a01caec 244 WARNING_NOT_RUN_MSG;
apalmieri 0:7b0a5a01caec 245 } else {
apalmieri 0:7b0a5a01caec 246 TESEO_APP_LOG_INFO("start odo subystem.\r\n");
apalmieri 0:7b0a5a01caec 247 gnss.startOdo(1);
apalmieri 0:7b0a5a01caec 248 }
apalmieri 0:7b0a5a01caec 249 break;
apalmieri 0:7b0a5a01caec 250 case APP_CMD_STOPODO:
apalmieri 0:7b0a5a01caec 251 sAppCmd = APP_CMD_IDLE;
apalmieri 0:7b0a5a01caec 252 if(!gnssRunning) {
apalmieri 0:7b0a5a01caec 253 WARNING_NOT_RUN_MSG;
apalmieri 0:7b0a5a01caec 254 } else {
apalmieri 0:7b0a5a01caec 255 TESEO_APP_LOG_INFO("stop odo subystem.\r\n");
apalmieri 0:7b0a5a01caec 256 gnss.stopOdo();
apalmieri 0:7b0a5a01caec 257 }
apalmieri 0:7b0a5a01caec 258 break;
apalmieri 0:7b0a5a01caec 259 case APP_CMD_ENDATALOG:
apalmieri 0:7b0a5a01caec 260 sAppCmd = APP_CMD_IDLE;
apalmieri 0:7b0a5a01caec 261 if(!gnssRunning) {
apalmieri 0:7b0a5a01caec 262 WARNING_NOT_RUN_MSG;
apalmieri 0:7b0a5a01caec 263 } else {
apalmieri 0:7b0a5a01caec 264 TESEO_APP_LOG_INFO("enable datalog.\r\n");
apalmieri 0:7b0a5a01caec 265 _AppEnDatalogging(gnss.isDataloggingSupported());
apalmieri 0:7b0a5a01caec 266 }
apalmieri 0:7b0a5a01caec 267 break;
apalmieri 0:7b0a5a01caec 268 case APP_CMD_CONFDATALOG:
apalmieri 0:7b0a5a01caec 269 sAppCmd = APP_CMD_IDLE;
apalmieri 0:7b0a5a01caec 270 if(!gnssRunning) {
apalmieri 0:7b0a5a01caec 271 WARNING_NOT_RUN_MSG;
apalmieri 0:7b0a5a01caec 272 } else {
apalmieri 0:7b0a5a01caec 273 TESEO_APP_LOG_INFO("config datalog.\r\n");
apalmieri 0:7b0a5a01caec 274 _AppDatalogCfg();
apalmieri 0:7b0a5a01caec 275 }
apalmieri 0:7b0a5a01caec 276 break;
apalmieri 0:7b0a5a01caec 277 case APP_CMD_STARTDATALOG:
apalmieri 0:7b0a5a01caec 278 sAppCmd = APP_CMD_IDLE;
apalmieri 0:7b0a5a01caec 279 if(!gnssRunning) {
apalmieri 0:7b0a5a01caec 280 WARNING_NOT_RUN_MSG;
apalmieri 0:7b0a5a01caec 281 } else {
apalmieri 0:7b0a5a01caec 282 TESEO_APP_LOG_INFO("start datalog.\r\n");
apalmieri 0:7b0a5a01caec 283 gnss.startDatalog();
apalmieri 0:7b0a5a01caec 284 }
apalmieri 0:7b0a5a01caec 285 break;
apalmieri 0:7b0a5a01caec 286 case APP_CMD_STOPDATALOG:
apalmieri 0:7b0a5a01caec 287 sAppCmd = APP_CMD_IDLE;
apalmieri 0:7b0a5a01caec 288 if(!gnssRunning) {
apalmieri 0:7b0a5a01caec 289 WARNING_NOT_RUN_MSG;
apalmieri 0:7b0a5a01caec 290 } else {
apalmieri 0:7b0a5a01caec 291 TESEO_APP_LOG_INFO("stop datalog.\r\n");
apalmieri 0:7b0a5a01caec 292 gnss.stopDatalog();
apalmieri 0:7b0a5a01caec 293 }
apalmieri 0:7b0a5a01caec 294 break;
apalmieri 0:7b0a5a01caec 295 case APP_CMD_ERASEDATALOG:
apalmieri 0:7b0a5a01caec 296 sAppCmd = APP_CMD_IDLE;
apalmieri 0:7b0a5a01caec 297 if(!gnssRunning) {
apalmieri 0:7b0a5a01caec 298 WARNING_NOT_RUN_MSG;
apalmieri 0:7b0a5a01caec 299 } else {
apalmieri 0:7b0a5a01caec 300 TESEO_APP_LOG_INFO("erase datalog.\r\n");
apalmieri 0:7b0a5a01caec 301 gnss.eraseDatalog();
apalmieri 0:7b0a5a01caec 302 }
apalmieri 0:7b0a5a01caec 303 break;
apalmieri 0:7b0a5a01caec 304 case APP_CMD_VERBOSE:
apalmieri 0:7b0a5a01caec 305 sAppCmd = APP_CMD_IDLE;
apalmieri 0:7b0a5a01caec 306 if(!gnssRunning) {
apalmieri 0:7b0a5a01caec 307 WARNING_NOT_RUN_MSG;
apalmieri 0:7b0a5a01caec 308 } else {
apalmieri 0:7b0a5a01caec 309 TESEO_APP_LOG_INFO("set verbose mode.\r\n");
apalmieri 0:7b0a5a01caec 310 gnss.setVerboseMode(level);
apalmieri 0:7b0a5a01caec 311 }
apalmieri 0:7b0a5a01caec 312 break;
apalmieri 0:7b0a5a01caec 313 case APP_CMD_GET_DEVICE_INFO:
apalmieri 0:7b0a5a01caec 314 sAppCmd = APP_CMD_IDLE;
apalmieri 0:7b0a5a01caec 315 if(!gnssRunning) {
apalmieri 0:7b0a5a01caec 316 WARNING_NOT_RUN_MSG;
apalmieri 0:7b0a5a01caec 317 } else {
apalmieri 0:7b0a5a01caec 318 TESEO_APP_LOG_INFO("get device info.\r\n");
apalmieri 0:7b0a5a01caec 319 if(gnss.haveDeviceInfo()) {
apalmieri 0:7b0a5a01caec 320 TESEO_APP_LOG_INFO(gnss.getDeviceInfo());
apalmieri 0:7b0a5a01caec 321 }
apalmieri 0:7b0a5a01caec 322 TESEO_APP_LOG_INFO("\r\n");
apalmieri 0:7b0a5a01caec 323 }
apalmieri 0:7b0a5a01caec 324 break;
apalmieri 0:7b0a5a01caec 325 }
apalmieri 0:7b0a5a01caec 326 Thread::yield(); // Allow other threads to run
apalmieri 0:7b0a5a01caec 327 }
apalmieri 0:7b0a5a01caec 328 }
apalmieri 0:7b0a5a01caec 329
apalmieri 0:7b0a5a01caec 330 int main() {
apalmieri 0:7b0a5a01caec 331 Thread consoleThread;
apalmieri 0:7b0a5a01caec 332 Thread cmdThread;
apalmieri 0:7b0a5a01caec 333
apalmieri 0:7b0a5a01caec 334 consoleThread.set_priority(osPriorityIdle);
apalmieri 0:7b0a5a01caec 335 cmdThread.set_priority(osPriorityIdle);
apalmieri 0:7b0a5a01caec 336
apalmieri 0:7b0a5a01caec 337 serialDebug.format(8, Serial::None, 1);
apalmieri 0:7b0a5a01caec 338 serialDebug.baud(115200);
apalmieri 0:7b0a5a01caec 339 consoleThread.start(_ConsoleRxHandler);
apalmieri 0:7b0a5a01caec 340
apalmieri 0:7b0a5a01caec 341 gnss.reset();
apalmieri 0:7b0a5a01caec 342 gnss.onLocationUpdate(locationHandler);
apalmieri 0:7b0a5a01caec 343 TESEO_APP_LOG_INFO("Success to new GNSS.\r\n");
apalmieri 0:7b0a5a01caec 344
apalmieri 0:7b0a5a01caec 345 _AppShowCmd();
apalmieri 0:7b0a5a01caec 346 cmdThread.start(_ExecAppCmd);
apalmieri 0:7b0a5a01caec 347
apalmieri 0:7b0a5a01caec 348 while(1) {
apalmieri 0:7b0a5a01caec 349 Thread::yield();
apalmieri 0:7b0a5a01caec 350 }
apalmieri 0:7b0a5a01caec 351
apalmieri 0:7b0a5a01caec 352 }
apalmieri 0:7b0a5a01caec 353
apalmieri 0:7b0a5a01caec 354 static void
apalmieri 0:7b0a5a01caec 355 _AppShowLastPosition(const GPSProvider::LocationUpdateParams_t *lastLoc)
apalmieri 0:7b0a5a01caec 356 {
apalmieri 0:7b0a5a01caec 357 char msg[256];
apalmieri 0:7b0a5a01caec 358 GPSProvider::LocationUpdateParams_t lastLocation = *lastLoc;
apalmieri 0:7b0a5a01caec 359
apalmieri 0:7b0a5a01caec 360 if(lastLocation.valid == true) {
apalmieri 0:7b0a5a01caec 361 sprintf(msg,"Latitude:\t\t[ %.0f' %d'' ]\n\r",
apalmieri 0:7b0a5a01caec 362 (lastLocation.lat - ((int)lastLocation.lat % 100)) / 100,
apalmieri 0:7b0a5a01caec 363 ((int)lastLocation.lat % 100));
apalmieri 0:7b0a5a01caec 364 TESEO_APP_LOG_INFO(msg);
apalmieri 0:7b0a5a01caec 365
apalmieri 0:7b0a5a01caec 366 sprintf(msg,"Longitude:\t\t[ %.0f' %d'' ]\n\r",
apalmieri 0:7b0a5a01caec 367 (lastLocation.lon - ((int)lastLocation.lon % 100)) / 100,
apalmieri 0:7b0a5a01caec 368 ((int)lastLocation.lon % 100));
apalmieri 0:7b0a5a01caec 369 TESEO_APP_LOG_INFO(msg);
apalmieri 0:7b0a5a01caec 370
apalmieri 0:7b0a5a01caec 371 sprintf(msg,"Altitude:\t\t[ %.2f ]\n\r",
apalmieri 0:7b0a5a01caec 372 lastLocation.altitude);
apalmieri 0:7b0a5a01caec 373 TESEO_APP_LOG_INFO(msg);
apalmieri 0:7b0a5a01caec 374
apalmieri 0:7b0a5a01caec 375 sprintf(msg,"Satellites locked:\t[ %d ]\n\r",
apalmieri 0:7b0a5a01caec 376 lastLocation.numGPSSVs);
apalmieri 0:7b0a5a01caec 377 TESEO_APP_LOG_INFO(msg);
apalmieri 0:7b0a5a01caec 378
apalmieri 0:7b0a5a01caec 379 sprintf(msg, "UTC:\t\t\t[ %d ]\n\r",
apalmieri 0:7b0a5a01caec 380 (int)lastLocation.utcTime);
apalmieri 0:7b0a5a01caec 381 TESEO_APP_LOG_INFO(msg);
apalmieri 0:7b0a5a01caec 382
apalmieri 0:7b0a5a01caec 383 } else {
apalmieri 0:7b0a5a01caec 384 sprintf(msg, "Last position wasn't valid.\n\n\r");
apalmieri 0:7b0a5a01caec 385 TESEO_APP_LOG_INFO(msg);
apalmieri 0:7b0a5a01caec 386 }
apalmieri 0:7b0a5a01caec 387 }
apalmieri 0:7b0a5a01caec 388
apalmieri 0:7b0a5a01caec 389 static void
apalmieri 0:7b0a5a01caec 390 _AppEnGeofence(const bool isGeofenceSupported)
apalmieri 0:7b0a5a01caec 391 {
apalmieri 0:7b0a5a01caec 392 if(isGeofenceSupported) {
apalmieri 0:7b0a5a01caec 393 gps_provider_error_t ret = gnss.enableGeofence();
apalmieri 0:7b0a5a01caec 394 if(ret == GPS_ERROR_NONE) {
apalmieri 0:7b0a5a01caec 395 TESEO_APP_LOG_INFO("Enabling Geofencing subsystem...\n\r");
apalmieri 0:7b0a5a01caec 396 }
apalmieri 0:7b0a5a01caec 397 } else {
apalmieri 0:7b0a5a01caec 398 TESEO_APP_LOG_INFO("Geofencing is not supported!\n\r");
apalmieri 0:7b0a5a01caec 399 }
apalmieri 0:7b0a5a01caec 400
apalmieri 0:7b0a5a01caec 401 }
apalmieri 0:7b0a5a01caec 402
apalmieri 0:7b0a5a01caec 403 static void
apalmieri 0:7b0a5a01caec 404 _AppGeofenceCfg(void)
apalmieri 0:7b0a5a01caec 405 {
apalmieri 0:7b0a5a01caec 406 GPSGeofence gf;
apalmieri 0:7b0a5a01caec 407
apalmieri 0:7b0a5a01caec 408 switch (geofenceId) {
apalmieri 0:7b0a5a01caec 409 case LecceId:
apalmieri 0:7b0a5a01caec 410 gf.setGeofenceCircle(STLecce);
apalmieri 0:7b0a5a01caec 411 break;
apalmieri 0:7b0a5a01caec 412 case CataniaId:
apalmieri 0:7b0a5a01caec 413 gf.setGeofenceCircle(Catania);
apalmieri 0:7b0a5a01caec 414 break;
apalmieri 0:7b0a5a01caec 415 }
apalmieri 0:7b0a5a01caec 416 /*
apalmieri 0:7b0a5a01caec 417 GPSGeofence::GeofenceCircle_t c = gf.getGeofenceCircle();
apalmieri 0:7b0a5a01caec 418 printf("_AppGeofenceCfg id=%d\r\n", c.id);
apalmieri 0:7b0a5a01caec 419 printf("_AppGeofenceCfg en=%d\r\n", c.enabled);
apalmieri 0:7b0a5a01caec 420 printf("_AppGeofenceCfg tol=%d\r\n", c.tolerance);
apalmieri 0:7b0a5a01caec 421 printf("_AppGeofenceCfg lat=%.2f\r\n", c.lat);
apalmieri 0:7b0a5a01caec 422 printf("_AppGeofenceCfg lon=%.2f\r\n", c.lon);
apalmieri 0:7b0a5a01caec 423 printf("_AppGeofenceCfg radius=%.2f\r\n", c.radius);
apalmieri 0:7b0a5a01caec 424 */
apalmieri 0:7b0a5a01caec 425
apalmieri 0:7b0a5a01caec 426 GPSGeofence *geofenceTable[] = {&gf};
apalmieri 0:7b0a5a01caec 427
apalmieri 0:7b0a5a01caec 428 gnss.onGeofenceCfgMessage(geofenceCfg);
apalmieri 0:7b0a5a01caec 429 gnss.onGeofenceStatusMessage(geofenceStatus);
apalmieri 0:7b0a5a01caec 430 gps_provider_error_t ret = gnss.configGeofences(geofenceTable, sizeof(geofenceTable)/sizeof(GPSGeofence *));
apalmieri 0:7b0a5a01caec 431 if(ret == GPS_ERROR_NONE) {
apalmieri 0:7b0a5a01caec 432 TESEO_APP_LOG_INFO("Configuring Geofence circles...\n\r");
apalmieri 0:7b0a5a01caec 433 }
apalmieri 0:7b0a5a01caec 434
apalmieri 0:7b0a5a01caec 435 }
apalmieri 0:7b0a5a01caec 436
apalmieri 0:7b0a5a01caec 437 static void
apalmieri 0:7b0a5a01caec 438 _AppEnOdometer(const bool isOdometerSupported)
apalmieri 0:7b0a5a01caec 439 {
apalmieri 0:7b0a5a01caec 440 if(isOdometerSupported) {
apalmieri 0:7b0a5a01caec 441 gps_provider_error_t ret = gnss.enableOdo();
apalmieri 0:7b0a5a01caec 442 if(ret == GPS_ERROR_NONE) {
apalmieri 0:7b0a5a01caec 443 TESEO_APP_LOG_INFO("Enabling Odometer subsystem...\n\r");
apalmieri 0:7b0a5a01caec 444 }
apalmieri 0:7b0a5a01caec 445 } else {
apalmieri 0:7b0a5a01caec 446 TESEO_APP_LOG_INFO("Odometer is not supported!\n\r");
apalmieri 0:7b0a5a01caec 447 }
apalmieri 0:7b0a5a01caec 448
apalmieri 0:7b0a5a01caec 449 }
apalmieri 0:7b0a5a01caec 450
apalmieri 0:7b0a5a01caec 451 static void
apalmieri 0:7b0a5a01caec 452 _AppEnDatalogging(const bool isDataloggingSupported)
apalmieri 0:7b0a5a01caec 453 {
apalmieri 0:7b0a5a01caec 454 if(isDataloggingSupported) {
apalmieri 0:7b0a5a01caec 455 gps_provider_error_t ret = gnss.enableDatalog();
apalmieri 0:7b0a5a01caec 456 if(ret == GPS_ERROR_NONE) {
apalmieri 0:7b0a5a01caec 457 TESEO_APP_LOG_INFO("Enabling Datalog subsystem...\n\r");
apalmieri 0:7b0a5a01caec 458 }
apalmieri 0:7b0a5a01caec 459 } else {
apalmieri 0:7b0a5a01caec 460 TESEO_APP_LOG_INFO("Datalog is not supported!\n\r");
apalmieri 0:7b0a5a01caec 461 }
apalmieri 0:7b0a5a01caec 462
apalmieri 0:7b0a5a01caec 463 }
apalmieri 0:7b0a5a01caec 464
apalmieri 0:7b0a5a01caec 465 static void
apalmieri 0:7b0a5a01caec 466 _AppDatalogCfg(void)
apalmieri 0:7b0a5a01caec 467 {
apalmieri 0:7b0a5a01caec 468 bool enableBufferFullAlarm = false;
apalmieri 0:7b0a5a01caec 469 bool enableCircularBuffer = true;
apalmieri 0:7b0a5a01caec 470 unsigned minRate = 5;
apalmieri 0:7b0a5a01caec 471 unsigned minSpeed = 0;
apalmieri 0:7b0a5a01caec 472 unsigned minPosition = 0;
apalmieri 0:7b0a5a01caec 473 int logMask = 1;
apalmieri 0:7b0a5a01caec 474
apalmieri 0:7b0a5a01caec 475 GPSDatalog dl(enableBufferFullAlarm,
apalmieri 0:7b0a5a01caec 476 enableCircularBuffer,
apalmieri 0:7b0a5a01caec 477 minRate,
apalmieri 0:7b0a5a01caec 478 minSpeed,
apalmieri 0:7b0a5a01caec 479 minPosition,
apalmieri 0:7b0a5a01caec 480 logMask);
apalmieri 0:7b0a5a01caec 481
apalmieri 0:7b0a5a01caec 482 gps_provider_error_t ret = gnss.configDatalog(&dl);
apalmieri 0:7b0a5a01caec 483 if(ret == GPS_ERROR_NONE) {
apalmieri 0:7b0a5a01caec 484 TESEO_APP_LOG_INFO("Configuring Datalog...\n\r");
apalmieri 0:7b0a5a01caec 485 }
apalmieri 0:7b0a5a01caec 486 }
apalmieri 0:7b0a5a01caec 487
apalmieri 0:7b0a5a01caec 488 static void
apalmieri 0:7b0a5a01caec 489 _AppShowCmd(void)
apalmieri 0:7b0a5a01caec 490 {
apalmieri 0:7b0a5a01caec 491 TESEO_APP_LOG_INFO("Location commands:\r\n");
apalmieri 0:7b0a5a01caec 492 TESEO_APP_LOG_INFO(" help - help to show supported commands\r\n");
apalmieri 0:7b0a5a01caec 493 TESEO_APP_LOG_INFO(" start - begin location app\r\n");
apalmieri 0:7b0a5a01caec 494 TESEO_APP_LOG_INFO(" stop - end location app\r\n");
apalmieri 0:7b0a5a01caec 495 TESEO_APP_LOG_INFO(" getlastloc - get last location\r\n");
apalmieri 0:7b0a5a01caec 496 TESEO_APP_LOG_INFO(" en-geo - enable Geofence\r\n");
apalmieri 0:7b0a5a01caec 497 TESEO_APP_LOG_INFO(" geo-c - config Geofence [c=l Lecce, c=t Catania]\r\n");
apalmieri 0:7b0a5a01caec 498 TESEO_APP_LOG_INFO(" req-geo - request Geofence status\r\n");
apalmieri 0:7b0a5a01caec 499 TESEO_APP_LOG_INFO(" en-odo - enable Odoemter\r\n");
apalmieri 0:7b0a5a01caec 500 TESEO_APP_LOG_INFO(" start-odo - start Ododmeter [demo distance 1m]\r\n");
apalmieri 0:7b0a5a01caec 501 TESEO_APP_LOG_INFO(" stop-odo - stop Ododmeter\r\n");
apalmieri 0:7b0a5a01caec 502 TESEO_APP_LOG_INFO(" en-datalog - enable Datalog\r\n");
apalmieri 0:7b0a5a01caec 503 TESEO_APP_LOG_INFO(" cfg-dl - config Datalog\r\n");
apalmieri 0:7b0a5a01caec 504 TESEO_APP_LOG_INFO(" start-dl - start Datalog\r\n");
apalmieri 0:7b0a5a01caec 505 TESEO_APP_LOG_INFO(" stop-dl - stop Datalog\r\n");
apalmieri 0:7b0a5a01caec 506 TESEO_APP_LOG_INFO(" erase-dl - erase Datalog\r\n");
apalmieri 0:7b0a5a01caec 507 TESEO_APP_LOG_INFO(" verbose-l - nmea msg verbose mode [l=1 normal, l=2 debug]\r\n");
apalmieri 0:7b0a5a01caec 508 TESEO_APP_LOG_INFO(" reset - reset GNSS\r\n");
apalmieri 0:7b0a5a01caec 509 TESEO_APP_LOG_INFO(" getdevinfo - get device info\r\n");
apalmieri 0:7b0a5a01caec 510 }
apalmieri 0:7b0a5a01caec 511
apalmieri 0:7b0a5a01caec 512 static void
apalmieri 0:7b0a5a01caec 513 _AppCmdProcess(char *pCmd)
apalmieri 0:7b0a5a01caec 514 {
apalmieri 0:7b0a5a01caec 515 if (strcmp(pCmd, "help") == 0) {
apalmieri 0:7b0a5a01caec 516 sAppCmd = APP_CMD_HELP;
apalmieri 0:7b0a5a01caec 517 } else if (strcmp(pCmd, "start") == 0) {
apalmieri 0:7b0a5a01caec 518 sAppCmd = APP_CMD_START;
apalmieri 0:7b0a5a01caec 519 } else if (strcmp(pCmd, "stop") == 0) {
apalmieri 0:7b0a5a01caec 520 sAppCmd = APP_CMD_STOP;
apalmieri 0:7b0a5a01caec 521 } else if (strcmp(pCmd, "getlastloc") == 0) {
apalmieri 0:7b0a5a01caec 522 sAppCmd = APP_CMD_GETLASTLOC;
apalmieri 0:7b0a5a01caec 523 } else if (strcmp(pCmd, "en-geo") == 0) {
apalmieri 0:7b0a5a01caec 524 sAppCmd = APP_CMD_ENGEOFENCE;
apalmieri 0:7b0a5a01caec 525 } else if (strcmp(pCmd, "geo-l") == 0) {
apalmieri 0:7b0a5a01caec 526 geofenceId = LecceId;
apalmieri 0:7b0a5a01caec 527 sAppCmd = APP_CMD_CONFGEOFENCE;
apalmieri 0:7b0a5a01caec 528 } else if (strcmp(pCmd, "geo-t") == 0) {
apalmieri 0:7b0a5a01caec 529 geofenceId = CataniaId;
apalmieri 0:7b0a5a01caec 530 sAppCmd = APP_CMD_CONFGEOFENCE;
apalmieri 0:7b0a5a01caec 531 } else if (strcmp(pCmd, "req-geo") == 0) {
apalmieri 0:7b0a5a01caec 532 sAppCmd = APP_CMD_GEOFENCEREQ;
apalmieri 0:7b0a5a01caec 533 } else if (strcmp(pCmd, "en-odo") == 0) {
apalmieri 0:7b0a5a01caec 534 sAppCmd = APP_CMD_ENODO;
apalmieri 0:7b0a5a01caec 535 } else if (strcmp(pCmd, "start-odo") == 0) {
apalmieri 0:7b0a5a01caec 536 sAppCmd = APP_CMD_STARTODO;
apalmieri 0:7b0a5a01caec 537 } else if (strcmp(pCmd, "stop-odo") == 0) {
apalmieri 0:7b0a5a01caec 538 sAppCmd = APP_CMD_STOPODO;
apalmieri 0:7b0a5a01caec 539 } else if (strcmp(pCmd, "en-datalog") == 0) {
apalmieri 0:7b0a5a01caec 540 sAppCmd = APP_CMD_ENDATALOG;
apalmieri 0:7b0a5a01caec 541 } else if (strcmp(pCmd, "cfg-dl") == 0) {
apalmieri 0:7b0a5a01caec 542 sAppCmd = APP_CMD_CONFDATALOG;
apalmieri 0:7b0a5a01caec 543 } else if (strcmp(pCmd, "start-dl") == 0) {
apalmieri 0:7b0a5a01caec 544 sAppCmd = APP_CMD_STARTDATALOG;
apalmieri 0:7b0a5a01caec 545 } else if (strcmp(pCmd, "stop-dl") == 0) {
apalmieri 0:7b0a5a01caec 546 sAppCmd = APP_CMD_STOPDATALOG;
apalmieri 0:7b0a5a01caec 547 } else if (strcmp(pCmd, "erase-dl") == 0) {
apalmieri 0:7b0a5a01caec 548 sAppCmd = APP_CMD_ERASEDATALOG;
apalmieri 0:7b0a5a01caec 549 } else if (strcmp(pCmd, "verbose-1") == 0) {
apalmieri 0:7b0a5a01caec 550 level = 1;
apalmieri 0:7b0a5a01caec 551 sAppCmd = APP_CMD_VERBOSE;
apalmieri 0:7b0a5a01caec 552 } else if (strcmp(pCmd, "verbose-2") == 0) {
apalmieri 0:7b0a5a01caec 553 level = 2;
apalmieri 0:7b0a5a01caec 554 sAppCmd = APP_CMD_VERBOSE;
apalmieri 0:7b0a5a01caec 555 } else if (strcmp(pCmd, "reset") == 0) {
apalmieri 0:7b0a5a01caec 556 sAppCmd = APP_CMD_RESET;
apalmieri 0:7b0a5a01caec 557 } else if (strcmp(pCmd, "getdevinfo") == 0) {
apalmieri 0:7b0a5a01caec 558 sAppCmd = APP_CMD_GET_DEVICE_INFO;
apalmieri 0:7b0a5a01caec 559 } else {
apalmieri 0:7b0a5a01caec 560 TESEO_APP_LOG_INFO("\r\nUnknown command %s\r\n", pCmd);
apalmieri 0:7b0a5a01caec 561 }
apalmieri 0:7b0a5a01caec 562
apalmieri 0:7b0a5a01caec 563 TESEO_APP_LOG_INFO("\r\n");
apalmieri 0:7b0a5a01caec 564 }