00001
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00056
00057
00058 #include <string.h>
00059
00060 #include "gpio.h"
00061
00062
00063 #include "FreeRTOS.h"
00064 #include "task.h"
00065 #include "queue.h"
00066 #include "semphr.h"
00067
00068 #include "datalog.h"
00069 #include "tracedump.h"
00070 #include "fsaccess.h"
00071 #include "sensor.h"
00072 #include "temperature.h"
00073 #include "light.h"
00074 #include "potentiometer.h"
00075
00076 #include "cptime.h"
00077
00078 #include "BasicSMTP.h"
00079
00080
00081
00083 #define DATALOG_LOGSQUEUE_SIZE 30
00084
00085
00086
00087
00090 #define DATALOG_LOGSQUEUE_HITHRESHOLD (DATALOG_LOGSQUEUE_SIZE*70/100)
00091
00094 #define DATALOG_LOGSQUEUE_LOTHRESHOLD (DATALOG_LOGSQUEUE_SIZE*30/100)
00095
00097 #define DATALOG_LOGFILE_MAXSIZE 20480
00098
00100 #define DATALOG_STACK_SIZE configMINIMAL_STACK_SIZE
00101
00103 #define LOGTOFILE_STACK_SIZE configMINIMAL_STACK_SIZE
00104
00106 #define DATALOG_INVALID_LOGSRC_ID (0xFFFFFFFF)
00107
00108
00109
00110
00111
00113 extern xSemaphoreHandle xLOGMutex;
00114
00116 const signed portCHAR *const pcStringLogDirectoryNameA = (signed portCHAR *)"A:/LOG";
00117 const signed portCHAR *const pcStringLogDirectoryNameB = (signed portCHAR *)"B:/LOG";
00118
00120 const signed portCHAR *pcStringCurrentLogDirectoryName;
00121
00123 static xTaskHandle xDataLogHndl = NULL;
00124
00126 static xTaskHandle xLogToFileHndl = NULL;
00127
00129 static eStatus xDataLogStatus = SYS_STATUS_STARTUP;
00130
00132 static xQueueHandle xLogsQueue = 0;
00133
00135 static unsigned portBASE_TYPE uxNbMsgsInLogsQueue = 0;
00136
00140 static char acLogFileName[25];
00141 static char acPreviousLogFileName[25];
00142
00144 char *acLogSourceName[12] = { "temp", "pot", "light", "pb1", "pb2", "pb3", "js",
00145 "ledb1", "ledb2", "ledm1", "ledm2", "lcd" };
00146
00148 static char acLogString[DATALOG_LOG_MAXSIZE];
00149
00151 static xLogDef axLogsPool[DATALOG_LOGSQUEUE_HITHRESHOLD];
00152
00154 static U8 u8FreeLogIdx = 0;
00155
00157 static char pcTempoDate[17];
00158
00160 extern time_t xcptime_LocalTime;
00161
00162 extern int sprintf(char *out, const char *format, ...);
00163
00164 static portTASK_FUNCTION( vDataLogTask, pvParameters );
00165 static portTASK_FUNCTION( vLogToFileTask, pvParameters );
00166 static int prv_xopen_current_logfile( void );
00167 static void prv_vsave_logs( int fd_current_logfile );
00168 void v_datalog_AddSensorLog( eLogSourceId SensorId );
00169 void prv_vdatalog_pool_log_free( void *pxLog );
00170
00171
00172
00173
00174 #if configCTRLPANEL_TRACE == 1
00175
00178 void v_datalog_trace( void )
00179 {
00180 NAKED_TRACE_COM2( "DATALOG:<%d><%d>", uxNbMsgsInLogsQueue, u8FreeLogIdx );
00181 }
00182 #endif
00183
00191 Bool bdatalog_start( unsigned portBASE_TYPE uxPriority )
00192 {
00193 int i;
00194
00195
00196 pcStringCurrentLogDirectoryName = pcStringLogDirectoryNameA;
00197
00198
00199 for( i=0; i<DATALOG_LOGSQUEUE_HITHRESHOLD; i++)
00200 axLogsPool[i].id = DATALOG_INVALID_LOGSRC_ID;
00201
00202
00203 if( pdPASS != xTaskCreate( vDataLogTask,
00204 ( const signed portCHAR * )"DLOG",
00205 DATALOG_STACK_SIZE, NULL, uxPriority,
00206 &xDataLogHndl ) )
00207 {
00208 xDataLogStatus = SYS_STATUS_DOWN;
00209 return FALSE;
00210 }
00211
00212
00213 if( pdPASS != xTaskCreate( vLogToFileTask,
00214 ( const signed portCHAR * )"LOGF",
00215 LOGTOFILE_STACK_SIZE, NULL, uxPriority +1,
00216 &xLogToFileHndl ) )
00217 {
00218 vTaskDelete( xDataLogHndl );
00219 xDataLogStatus = SYS_STATUS_DOWN;
00220 return FALSE;
00221 }
00222
00223
00224
00225 xLogsQueue = xQueueCreate( DATALOG_LOGSQUEUE_SIZE, sizeof( xLogDef * ) );
00226 if( 0 == xLogsQueue )
00227 {
00228 vTaskDelete( xDataLogHndl );
00229 vTaskDelete( xLogToFileHndl );
00230 return FALSE;
00231 }
00232
00233 return( TRUE );
00234 }
00235
00236
00242 eStatus xDataLog_GetStatus( void )
00243 {
00244 return( xDataLogStatus );
00245 }
00246
00247
00248
00253 static portTASK_FUNCTION( vDataLogTask, pvParameters )
00254 {
00255 portTickType xLastFocusTime;
00256 U8 u8TempWalkThrough = 0;
00257 U8 u8PotWalkThrough = 0;
00258 U8 u8LightWalkThrough = 0;
00259
00260
00261
00262 ( void ) pvParameters;
00263
00264 xDataLogStatus = SYS_STATUS_RUNNING;
00265
00266
00267 xLastFocusTime = xTaskGetTickCount();
00268
00269 for(;;)
00270 {
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 vTaskDelayUntil( &xLastFocusTime, ( portTickType ) 1000 / portTICK_RATE_MS );
00284
00285
00286 u8TempWalkThrough++;
00287 if( ul_temp_lograte <= u8TempWalkThrough )
00288 {
00289 u8TempWalkThrough = 0;
00290
00291 v_datalog_AddSensorLog( DATALOG_ID_TEMP );
00292 }
00293
00294
00295 u8PotWalkThrough++;
00296 if( ul_pot_lograte <= u8PotWalkThrough )
00297 {
00298 u8PotWalkThrough = 0;
00299
00300 v_datalog_AddSensorLog( DATALOG_ID_POT );
00301 }
00302
00303
00304 u8LightWalkThrough++;
00305 if( ul_light_lograte <= u8LightWalkThrough )
00306 {
00307 u8LightWalkThrough = 0;
00308
00309 v_datalog_AddSensorLog( DATALOG_ID_LIGHT );
00310 }
00311
00312 }
00313 }
00314
00315
00321 void v_datalog_AddSensorLog( eLogSourceId SensorId )
00322 {
00323 xLogDef *pxLog;
00324
00325
00326
00327 uxNbMsgsInLogsQueue = uxQueueMessagesWaiting( xLogsQueue );
00328 if( DATALOG_LOGSQUEUE_HITHRESHOLD <= uxNbMsgsInLogsQueue )
00329 {
00330
00331 vTaskSuspend( xLogToFileHndl );
00332 vTaskResume( xLogToFileHndl );
00333
00334
00335
00336 }
00337
00338
00339 pxLog = pxdatalog_log_alloc_init( DATALOG_ALLOC_DYNAMIC );
00340
00341 if( NULL != pxLog )
00342 {
00343
00344 pxLog->id = SensorId;
00345
00346
00347 if( FALSE == b_sensor_get_value( pxLog ) )
00348 {
00349 vdatalog_log_free( pxLog );
00350 return;
00351 }
00352
00353
00354 if( errQUEUE_FULL == xQueueSend( xLogsQueue, (void *)&pxLog, 0 ) )
00355 {
00356
00357 vdatalog_log_free( pxLog );
00358
00359 vTaskSuspend( xLogToFileHndl );
00360 vTaskResume( xLogToFileHndl );
00361
00362
00363
00364 }
00365 }
00366 }
00367
00368
00377 portBASE_TYPE x_datalog_AddLogFromISR( xLogDef *pxLog )
00378 {
00379 portBASE_TYPE xYieldRequired = pdFALSE;
00380
00381
00382 if( ( NULL != pxLog ) && ( DATALOG_LOGSQUEUE_SIZE != uxNbMsgsInLogsQueue ) )
00383 {
00384
00385
00386
00387
00388
00389
00390 if( DATALOG_LOGSQUEUE_SIZE == uxNbMsgsInLogsQueue )
00391 {
00392 vdatalog_log_free( pxLog );
00393 }
00394 else
00395 {
00396 portENTER_CRITICAL();
00397 xQueueSendFromISR( xLogsQueue, (void *)&pxLog, &xYieldRequired );
00398 portEXIT_CRITICAL();
00399 }
00400 }
00401 return( xYieldRequired );
00402 }
00403
00408 static portTASK_FUNCTION( vLogToFileTask, pvParameters )
00409 {
00410 int fd_current_logfile;
00411
00412
00413
00414 ( void ) pvParameters;
00415
00416 xDataLogStatus = SYS_STATUS_RUNNING;
00417
00418
00419 *acLogFileName = '\0';
00420 *acPreviousLogFileName = '\0';
00421
00422 for(;;)
00423 {
00424
00425 vTaskSuspend( NULL );
00426
00427
00428
00429
00430
00431
00432
00433 if( FALSE == x_supervisor_SemaphoreTake( xLOGMutex, 0 ) )
00434 {
00435
00436
00437 prv_vsave_logs( -1 );
00438 continue;
00439 }
00440
00441
00442
00443 fd_current_logfile = prv_xopen_current_logfile();
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 prv_vsave_logs(fd_current_logfile);
00454
00455
00456 x_supervisor_SemaphoreGive( xLOGMutex );
00457 }
00458 }
00459
00460
00468 xLogDef *pxdatalog_log_alloc_init( Bool bAllocType )
00469 {
00470 xLogDef *pxLog;
00471 void (*pfFreeLogStruct)(void *);
00472
00473
00474
00475 if( DATALOG_ALLOC_DYNAMIC == bAllocType )
00476 {
00477 pxLog = ( xLogDef * )pvPortMalloc( sizeof( xLogDef ) );
00478 pfFreeLogStruct = vPortFree;
00479
00480 }
00481 else
00482 {
00483
00484 if( DATALOG_INVALID_LOGSRC_ID != axLogsPool[u8FreeLogIdx].id )
00485 {
00486 return( NULL );
00487 }
00488 else
00489 {
00490 pxLog = &(axLogsPool[u8FreeLogIdx++]);
00491 u8FreeLogIdx = (u8FreeLogIdx == DATALOG_LOGSQUEUE_HITHRESHOLD) ? 0 : u8FreeLogIdx;
00492 pfFreeLogStruct = prv_vdatalog_pool_log_free;
00493 }
00494 }
00495
00496
00497 if( NULL != pxLog )
00498 {
00499 pxLog->rawdate = xcptime_LocalTime;
00500 pxLog->pfFreeLogStruct = pfFreeLogStruct;
00501 pxLog->pcStringLog = NULL;
00502 pxLog->pfFreeStringLog = NULL;
00503 }
00504
00505 return( pxLog );
00506 }
00507
00508
00515 void vdatalog_log_free( xLogDef *pxLog )
00516 {
00517
00518 if( NULL != pxLog->pfFreeStringLog)
00519 {
00520 pxLog->pfFreeStringLog( pxLog->pcStringLog );
00521 }
00522
00523 pxLog->pfFreeLogStruct( pxLog );
00524 }
00525
00526
00533 void prv_vdatalog_pool_log_free( void *pxLog )
00534 {
00535 ((xLogDef *)pxLog)->id = DATALOG_INVALID_LOGSRC_ID;
00536 }
00537
00538
00546 void vdatalog_make_logstring( xLogDef *pxLog, signed portCHAR *pcLogString )
00547 {
00548 struct tm *pxLogDate;
00549
00550
00551
00552 pxLogDate = gmtime( &(pxLog->rawdate) );
00553
00554
00555
00556
00557 if( pxLogDate->tm_year >= 100 )
00558 pxLogDate->tm_year -= 100;
00559 sprintf( (char *)pcLogString, "%s | %.2d/%.2d/%.2d %.2d:%.2d:%.2d | %s\r\n",
00560 acLogSourceName[pxLog->id], pxLogDate->tm_mon +1,
00561 pxLogDate->tm_mday, pxLogDate->tm_year, pxLogDate->tm_hour,
00562 pxLogDate->tm_min, pxLogDate->tm_sec, pxLog->pcStringLog );
00563 }
00564
00565
00566
00572 static int prv_xopen_current_logfile( void )
00573 {
00574 int fd_current_logfile;
00575 struct tm *pxDate;
00576
00577
00578
00579
00580 while( 1 )
00581 {
00582 fd_current_logfile = -1;
00583
00584
00585 if( '\0' != *acLogFileName )
00586 {
00587 fd_current_logfile = open( acLogFileName, O_APPEND );
00588
00589
00590 if( -1 != fd_current_logfile )
00591 {
00592 if( DATALOG_LOGFILE_MAXSIZE <= fsaccess_file_get_size( fd_current_logfile ) )
00593 {
00594
00595 v_cptime_GetDateInFatStringFormat( pcTempoDate );
00596
00597 nav_file_dateset( (FS_STRING)pcTempoDate, FS_DATE_LAST_WRITE );
00598 close( fd_current_logfile );
00599 *acLogFileName = '\0';
00600 continue;
00601 }
00602 }
00603 else
00604 {
00605 *acLogFileName = '\0';
00606 continue;
00607 }
00608 }
00609 else
00610 {
00611
00612 pxDate = gmtime( &xcptime_LocalTime );
00613
00614
00615
00616
00617 if( pxDate->tm_year >= 100 )
00618 pxDate->tm_year -= 100;
00619
00620 sprintf( acLogFileName, "%s/%.2d%.2d%.2d_%.2d%.2d.log",
00621 pcStringCurrentLogDirectoryName, pxDate->tm_mon +1, pxDate->tm_mday,
00622 pxDate->tm_year, pxDate->tm_hour, pxDate->tm_min );
00623
00624 NAKED_TRACE_COM2( "Creating log file %s", acLogFileName );
00625
00626
00627 if( TRUE == fsaccess_IsDirPresent( (const char *)pcStringCurrentLogDirectoryName ) )
00628 {
00629
00630
00631 fd_current_logfile = open( acLogFileName, (O_CREAT|O_WRONLY) );
00632
00633 if ( *acPreviousLogFileName != '\0' )
00634 {
00635
00636 v_SMTP_Post(acPreviousLogFileName, acPreviousLogFileName);
00637 }
00638 strncpy(acPreviousLogFileName, acLogFileName, strlen(acLogFileName));
00639 }
00640 }
00641 if( -1 == fd_current_logfile )
00642 {
00643
00644 NAKED_TRACE_COM2( "Failed opening the current log file %s", acLogFileName );
00645
00646 break;
00647
00648 }
00649 else break;
00650 }
00651
00652 return( fd_current_logfile );
00653 }
00654
00655
00666 static void prv_vsave_logs( int fd_current_logfile )
00667 {
00668 xLogDef *pxLog;
00669 int iLogStringLen;
00670 portTickType xLastFocusTime;
00671
00672
00673
00674 xLastFocusTime = xTaskGetTickCount();
00675
00676
00677
00678
00679 while( DATALOG_LOGSQUEUE_LOTHRESHOLD < ( uxNbMsgsInLogsQueue = uxQueueMessagesWaiting( xLogsQueue ) ) )
00680 {
00681
00682
00683 if( pdTRUE == xQueueReceive( xLogsQueue, &pxLog, ( portTickType ) 0 ) )
00684 {
00685 if( -1 == fd_current_logfile )
00686 {
00687 vdatalog_log_free( pxLog );
00688 }
00689 else
00690 {
00691
00692 vdatalog_make_logstring( pxLog, (signed portCHAR *)acLogString );
00693
00694
00695 vdatalog_log_free( pxLog );
00696
00697
00698 iLogStringLen = strlen( acLogString );
00699 if( iLogStringLen != write( fd_current_logfile, acLogString, iLogStringLen ) )
00700 break;
00701
00702
00703 }
00704 }
00705
00706 vTaskDelayUntil( &xLastFocusTime, ( portTickType )TASK_DELAY_MS(20) );
00707 }
00708 if( -1 != fd_current_logfile )
00709 {
00710
00711 v_cptime_GetDateInFatStringFormat( pcTempoDate );
00712
00713 nav_file_dateset( (FS_STRING)pcTempoDate, FS_DATE_LAST_WRITE );
00714 close( fd_current_logfile );
00715 }
00716 }
00717
00718
00724 Bool b_datalog_set_current_log_drive_toDF( void )
00725 {
00726
00727
00728 if(*acLogFileName == 'B')
00729 {
00730 *acLogFileName = '\0';
00731 }
00732 pcStringCurrentLogDirectoryName = pcStringLogDirectoryNameA;
00733 return(pdTRUE);
00734 }
00735
00736
00742 Bool b_datalog_set_current_log_drive_toSDMMC( void )
00743 {
00744
00745
00746 if(*acLogFileName == 'A')
00747 {
00748 *acLogFileName = '\0';
00749 }
00750 pcStringCurrentLogDirectoryName = pcStringLogDirectoryNameB;
00751 return(pdTRUE);
00752 }