diff --git a/CMakeLists.txt b/CMakeLists.txt index c413d7c..261847f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,3 @@ PROJECT(lib_redAcore) -ADD_LIBRARY(redAcore TimingCore.cpp LogCore.cpp SignalCore.cpp BufferCore.cpp FunctionCore.cpp DeviceCore.cpp FileCore.cpp SelectCore.cpp SelectableCore.cpp) +ADD_LIBRARY(redAcore TimingCore.cpp DateTimeCore.cpp LogCore.cpp SignalCore.cpp BufferCore.cpp FunctionCore.cpp DeviceCore.cpp FileCore.cpp SelectCore.cpp SelectableCore.cpp) diff --git a/DateTimeCore.cpp b/DateTimeCore.cpp new file mode 100644 index 0000000..55df337 --- /dev/null +++ b/DateTimeCore.cpp @@ -0,0 +1,175 @@ +/* + * DateTimeCore.cpp + * + * Created on: 3 March 2017 + * Author: wentzelc + */ + +// redA Libraries +#include "DateTimeCore.h" + +// Standard C/C++ Libraries +#include +#include +#include +#include +#include + +//--------------------------------------------------------------------------- + +// Variable used to temp values with +static char ReturnStr[20]; + +//--------------------------------------------------------------------------- + +// Set current time on real-time clock +bool SetTime( unsigned char Hours, unsigned char Minutes, unsigned char Seconds ) +{ + struct tm NewTime; + struct timeval tv; + struct timezone tz; + + // Get current date and time + gettimeofday( &tv, &tz); + + // Change to new time + localtime_r( &tv.tv_sec, &NewTime ); + + NewTime.tm_hour = Hours; + NewTime.tm_min = Minutes; + NewTime.tm_sec = Seconds; + + // Convert back + tv.tv_sec = mktime( &NewTime ); + tv.tv_usec = 0; + + // Set date and new time + settimeofday( &tv, &tz); + return true; +} +//--------------------------------------------------------------------------- + +// Get current time from real-time clock +bool GetTime( unsigned char &Hours, unsigned char &Minutes, unsigned char &Seconds ) +{ + struct tm CurrentTime; + time_t UTC; + + // Get current date and time + time( &UTC ); + localtime_r( &UTC, &CurrentTime ); + + // Extract time + Hours = CurrentTime.tm_hour; + Minutes = CurrentTime.tm_min; + Seconds = CurrentTime.tm_sec; + + return true; +} +//--------------------------------------------------------------------------- + +// Set current date on real-time clock +bool SetDate( unsigned char Day, unsigned char Month, unsigned Year ) +{ + struct tm NewDate; + struct timeval tv; + struct timezone tz; + + // Get current date and time + gettimeofday( &tv, &tz ); + + // Change to new time + localtime_r( &tv.tv_sec, &NewDate ); + + NewDate.tm_year = Year - 1900; + NewDate.tm_mon = Month - 1; + NewDate.tm_mday = Day; + + // Convert back + tv.tv_sec = mktime( &NewDate ); + tv.tv_usec = 0; + + // Set date and new time + settimeofday( &tv, &tz); + + return true; +} +//--------------------------------------------------------------------------- + +// Get current data from real-time clock +bool GetDate( unsigned char &Day, unsigned char &Month, unsigned &Year ) +{ + struct tm CurrentDate; + time_t UTC; + + // Get current date and time + time( &UTC ); + localtime_r( &UTC, &CurrentDate ); + + // Extract date + Day = CurrentDate.tm_mday; + Month = CurrentDate.tm_mon + 1; + Year = CurrentDate.tm_year + 1900; + + return true; +} +//--------------------------------------------------------------------------- + +// Get the current date in a string +char const * GetDateStr( const char * DateSeparator ) +{ + unsigned char Day; + unsigned char Month; + unsigned int Year; + + // Get Date + GetDate( Day, Month, Year ); + + // Build String + sprintf( ReturnStr, "%04d%s%02d%s%02d", + Year, ((DateSeparator)? DateSeparator : "/"), Month, ((DateSeparator)? DateSeparator : "/"), Day ); + + // Return value + return (ReturnStr); +} +//--------------------------------------------------------------------------- + +char const * GetTimeStr( const char * TimeSeparator ) +{ + unsigned char Hours; + unsigned char Minutes; + unsigned char Seconds; + + // Get Date & Time + GetTime( Hours, Minutes, Seconds ); + + // Build String + sprintf( ReturnStr, "%02d%s%02d%s%02d", + Hours, ((TimeSeparator)? TimeSeparator : ":"), Minutes, ((TimeSeparator)? TimeSeparator : ":"), Seconds ); + + return (ReturnStr); +} +//--------------------------------------------------------------------------- + +char const * GetDateTimeStr( const char * DateSeparator, const char * TimeSeparator ) +{ + unsigned char Day; + unsigned char Month; + unsigned int Year; + unsigned char Hours; + unsigned char Minutes; + unsigned char Seconds; + + // Get Date & Time + GetDate( Day, Month, Year ); + GetTime( Hours, Minutes, Seconds ); + + // Build String + sprintf( ReturnStr, "%04d%s%02d%s%02d %02d%s%02d%s%02d", + Year, ((DateSeparator)? DateSeparator : "/"), Month, ((DateSeparator)? DateSeparator : "/"), Day, + Hours, ((TimeSeparator)? TimeSeparator : ":"), Minutes, ((TimeSeparator)? TimeSeparator : ":"), Seconds ); + + return (ReturnStr); +} +//--------------------------------------------------------------------------- + diff --git a/DateTimeCore.h b/DateTimeCore.h new file mode 100644 index 0000000..bfaaf60 --- /dev/null +++ b/DateTimeCore.h @@ -0,0 +1,32 @@ +/* + * DateTimeCore.h + * + * Created on: 3 Mar 2017 + * Author: wentzelc + */ + +#ifndef REDACORE_DATETIMECORE_H_ +#define REDACORE_DATETIMECORE_H_ + +// redA Libraries +/* none */ + +// Standard C/C++ Libraries +#include + +//--------------------------------------------------------------------------- + +// Get and set System Date and Time +bool SetTime( unsigned char Hours, unsigned char Minutes, unsigned char Seconds ); +bool GetTime( unsigned char &Hours, unsigned char &Minutes, unsigned char &Seconds ); + +bool SetDate( unsigned char Day, unsigned char Month, unsigned Year ); +bool GetDate( unsigned char &Day, unsigned char &Month, unsigned &Year ); + +char const * GetDateStr( const char * DateSeparator = NULL ); +char const * GetTimeStr( const char * TimeSeparator = NULL ); +char const * GetDateTimeStr( const char * DateSeparator = NULL, const char * TimeSeparator = NULL ); + +//--------------------------------------------------------------------------- + +#endif /* REDACORE_DATETIMECORE_H_ */ diff --git a/DeviceCore.cpp b/DeviceCore.cpp index d354ea1..b1f3bfc 100644 --- a/DeviceCore.cpp +++ b/DeviceCore.cpp @@ -446,7 +446,7 @@ bool CDeviceCore::UpdateSignedValue( TDeviceParam * Param, const int32_t Value, // Mark change & log event Changed = true; - Log->Message( DebugLevel, dlLow, "%s: '%s' %s - %u", Name, Param->Name, ((Init)? "initialised" : "changed"), *((int16_t*)Param->Value) ); + Log->Message( DebugLevel, dlLow, "%s: '%s' %s - %d", Name, Param->Name, ((Init)? "initialised" : "changed"), *((int16_t*)Param->Value) ); } break; @@ -458,7 +458,7 @@ bool CDeviceCore::UpdateSignedValue( TDeviceParam * Param, const int32_t Value, // Mark change & log event Changed = true; - Log->Message( DebugLevel, dlLow, "%s: '%s' %s - %u", Name, Param->Name, ((Init)? "initialised" : "changed"), *((int32_t*)Param->Value) ); + Log->Message( DebugLevel, dlLow, "%s: '%s' %s - %d", Name, Param->Name, ((Init)? "initialised" : "changed"), *((int32_t*)Param->Value) ); } break; @@ -518,24 +518,33 @@ bool CDeviceCore::UpdateStringValue( TDeviceParam * Param, const char * Value, c if (!Param || (Param->DataType != dtString)) return false; - // Update register - if (Init || !CompareParamString( (char*)Param->Value, Param->Len, Value, Len)) + switch (Param->DataType) { - if (Len >= Param->Len) { - // Copy full register length (ignore additional bytes) - memcpy( Param->Value, Value, Param->Len ); - ((char*)Param->Value)[ Param->Len ] = 0; // null terminate - } - else { - // Copy new value - memcpy( Param->Value, Value, Len ); - // Zero pad remaining - memset( &((char*)Param->Value)[Len], 0x0, (Param->Len - Len + 1) ); // Add null teriminate - } + case dtString : + // Update register + if (Init || !CompareParamString( (char*)Param->Value, Param->Len, Value, Len)) + { + if (Len >= Param->Len) { + // Copy full register length (ignore additional bytes) + memcpy( Param->Value, Value, Param->Len ); + ((char*)Param->Value)[ Param->Len ] = 0; // null terminate + } + else { + // Copy new value + memcpy( Param->Value, Value, Len ); + // Zero pad remaining + memset( &((char*)Param->Value)[Len], 0x0, (Param->Len - Len + 1) ); // Add null teriminate + } - // Mark Change - Changed = true; - Log->Message( DebugLevel, dlLow, "%s: '%s' %s - %s", Name, Param->Name, ((Init)? "initialised" : "changed"), (char*)Param->Value ); + // Mark Change + Changed = true; + Log->Message( DebugLevel, dlLow, "%s: '%s' %s - %s", Name, Param->Name, ((Init)? "initialised" : "changed"), (char*)Param->Value ); + } + break; + + default : + // Invalid Data Type + return false; } // Generate Channel Event if (Changed) { @@ -680,6 +689,115 @@ bool CDeviceCore::SetStringValue( TDeviceParam * Param, const char * Value, cons } //--------------------------------------------------------------------------- +bool CDeviceCore::SetValue( TDeviceParam * Param, const char * Value, const int Len, bool Force ) +{ + u_int32_t UnsignedVal; + int32_t SignedVal; + float FloatVal; + + char * TempStr; + bool UseTempStr = false; + + // Validate + if (!Param || !Value || !Len) + return false; + + // Check if string + if (Param->DataType == dtString) + { + // Simply set string + SetStringValue( Param, Value, Len, Force ); + } + else + { + // Ensure string is zero terminated + if (Value[Len] != 0) { + TempStr = (char *)malloc( Len+1 ); + memcpy( TempStr, Value, Len ); + TempStr[Len] = 0; + UseTempStr = true; + } + + // Convert to correct type + switch (Param->DataType) + { + case dtUnsigned16 : + case dtUnsigned32 : + UnsignedVal = (u_int32_t)strtoul( ((UseTempStr)? TempStr : Value), NULL, 10 ); + SetUnsignedValue( Param, UnsignedVal, Force ); + break; + + case dtSigned16 : + case dtSigned32 : + SignedVal = (u_int32_t)strtol( ((UseTempStr)? TempStr : Value), NULL, 10 ); + SetUnsignedValue( Param, SignedVal, Force ); + break; + + case dtFloat32 : + FloatVal = (u_int32_t) strtof( ((UseTempStr)? TempStr : Value), NULL ); + SetUnsignedValue( Param, FloatVal, Force ); + break; + + default : + return false; + } + + // Clear memory + if (UseTempStr) { + free( TempStr ); + } + } + return true; +} +//--------------------------------------------------------------------------- + +bool CDeviceCore::GetValue( TDeviceParam * Param, char * Value, int &Len ) +{ + // Validate + if (!Param || !Value) + return false; + + // Check if return value longer than actual value + switch (Param->DataType) + { + case dtUnsigned16 : + sprintf( Value, "%u", (*((u_int16_t*)Param->Value)) ); + break; + + case dtUnsigned32 : + sprintf( Value, "%u", (*((u_int32_t*)Param->Value)) ); + break; + + case dtSigned16 : + sprintf( Value, "%d", (*((int16_t*)Param->Value)) ); + break; + + case dtSigned32 : + sprintf( Value, "%d", (*((int32_t*)Param->Value)) ); + break; + + case dtFloat32 : + sprintf( Value, "%f", (*((float*)Param->Value)) ); + break; + + case dtString : + if (Len < Param->Len) + { + // Only copy requested no of chars + memcpy( Value, Param->Value, Len ); + Value[ Len ] = 0; + } + else + { + memcpy( Value, Param->Value, Param->Len ); + Value[ Param->Len ] = 0; + } + break; + } + return true; +} +//--------------------------------------------------------------------------- + bool CDeviceCore::CompareParamString( const char * ParamValue, const int ParamLen, const char * Value, const int Len ) { bool Match = true; diff --git a/DeviceCore.h b/DeviceCore.h index cc37a95..ff50060 100644 --- a/DeviceCore.h +++ b/DeviceCore.h @@ -95,13 +95,13 @@ protected: // Find Devices inline TDevice * GetDevice( const char * Name ) { TDevice * Device = FirstDevice; - while (Device && strcmp( Device->Name, Name )) + while (Device && strcasecmp( Device->Name, Name )) Device = Device->Next; return Device; } inline TDevice ** GetDevicePtr( const char * Name ) { TDevice ** Device = &FirstDevice; - while (*Device && strcmp( (*Device)->Name, Name )) + while (*Device && strcasecmp( (*Device)->Name, Name )) Device = &((*Device)->Next); return Device; } @@ -119,14 +119,14 @@ protected: inline TDeviceParam * GetDeviceParam( TDevice * Device, const char * Name ) { if (!Device) return NULL; TDeviceParam * Param = Device->FirstParam; - while (Param && strcmp( Param->Name, Name )) + while (Param && strcasecmp( Param->Name, Name )) Param = Param->Next; return Param; } inline TDeviceParam ** GetDeviceParamPtr( TDevice * Device, const char * Name ) { if (!Device) return NULL; TDeviceParam ** Param = &Device->FirstParam; - while (*Param && strcmp( (*Param)->Name, Name )) + while (*Param && strcasecmp( (*Param)->Name, Name )) Param = &((*Param)->Next); return Param; } @@ -196,6 +196,10 @@ public: bool SetSignedValue( TDeviceParam * Param, const int32_t Value, bool Force ); bool SetFloatValue( TDeviceParam * Param, const float Value, bool Force ); bool SetStringValue( TDeviceParam * Param, const char * Value, const int Len, bool Force ); + + // Text Interfaces + bool SetValue( TDeviceParam * Param, const char * Value, const int Len, bool Force ); + bool GetValue( TDeviceParam * Param, char * Value, int &Len ); }; //--------------------------------------------------------------------------- diff --git a/LogCore.cpp b/LogCore.cpp index 104642c..c1b3922 100644 --- a/LogCore.cpp +++ b/LogCore.cpp @@ -7,6 +7,7 @@ // redA Libraries #include "LogCore.h" +#include "DateTimeCore.h" // Standard C/C++ Libraries #include @@ -22,9 +23,9 @@ char LogStr[1000]; // Temporary var to create log messages, //--------------------------------------------------------------------------- -CLogCore::CLogCore( FILE * pFileOutput ) +CLogCore::CLogCore( FILE * pOutputFile ) { - FileOutput = pFileOutput; + OutputFile = pOutputFile; } //--------------------------------------------------------------------------- @@ -37,14 +38,19 @@ bool CLogCore::Message( EDebugLevel DebugLevel, EDebugLevel MsgLevel, const char return false; // Check debug level - if (!FileOutput || (MsgLevel > DebugLevel)) { + if (!OutputFile || (MsgLevel > DebugLevel)) { return true; } - // Show normal output + // Show Date & Time + if (OutputFile->_fileno > 3) { + fprintf( OutputFile, "%s", GetDateTimeStr( "/", ":" )); + } + + // Print formated message va_start( ArgPtr, Format ); - vfprintf( FileOutput, Format, ArgPtr ); - fprintf( FileOutput, "\r\n" ); + vfprintf( OutputFile, Format, ArgPtr ); + fprintf( OutputFile, "\r\n" ); va_end( ArgPtr ); return true; } @@ -59,7 +65,7 @@ bool CLogCore::Output( EDebugLevel DebugLevel, EDebugLevel MsgLevel, const short return false; // Check debug level - if (!FileOutput || (MsgLevel > DebugLevel)) { + if (!OutputFile || (MsgLevel > DebugLevel)) { return true; } @@ -67,10 +73,15 @@ bool CLogCore::Output( EDebugLevel DebugLevel, EDebugLevel MsgLevel, const short if (Len == -1) Len = strlen( Buffer ); + // Show date & time + if (OutputFile->_fileno > 3) { + fprintf( OutputFile, "%s", GetDateTimeStr( "/", ":" )); + } + // Show Lead if (Format && *Format) { va_start( ArgPtr, Format ); - vfprintf( FileOutput, Format, ArgPtr ); + vfprintf( OutputFile, Format, ArgPtr ); va_end( ArgPtr ); } @@ -78,11 +89,11 @@ bool CLogCore::Output( EDebugLevel DebugLevel, EDebugLevel MsgLevel, const short if (Show & OUT_COUNT) { // Print byte count - fprintf( FileOutput, " [%d] ", Len ); + fprintf( OutputFile, " [%d] ", Len ); // EOL if only count wanted if (Show & OUT_COUNT) { - fprintf( FileOutput, "\n" ); + fprintf( OutputFile, "\n" ); } } @@ -91,25 +102,25 @@ bool CLogCore::Output( EDebugLevel DebugLevel, EDebugLevel MsgLevel, const short { if (Show & OUT_ASIS) { // Print entire buffer as is (line feeds included) - fprintf( FileOutput, "%s", Buffer ); + fprintf( OutputFile, "%s", Buffer ); } else { // Ignore \r\n for (int i=0; i 126)) { if ((Show & OUT_CRLF) && ((Buffer[i] == '\r') || (Buffer[i] == '\n'))) - fprintf( FileOutput, "%c", Buffer[i] ); + fprintf( OutputFile, "%c", Buffer[i] ); else - fprintf( FileOutput, "." ); + fprintf( OutputFile, "." ); } else { - fprintf( FileOutput, "%c", Buffer[i] ); + fprintf( OutputFile, "%c", Buffer[i] ); } } } // Add EOL if not present or ignored if (!(Show & (OUT_ASIS | OUT_CRLF)) || (Buffer[Len-1] != '\n')) { - fprintf( FileOutput, "\n" ); + fprintf( OutputFile, "\n" ); } } @@ -118,9 +129,9 @@ bool CLogCore::Output( EDebugLevel DebugLevel, EDebugLevel MsgLevel, const short { // Print Hex values of individual bytes for (int i=0; i MilliSeconds)? true : false); } //--------------------------------------------------------------------------- +