diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c5ebd9..95d176b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,5 @@ PROJECT(lib_redAcore) -ADD_LIBRARY(redAcore TimingCore.cpp DateTimeCore.cpp LogCore.cpp SignalCore.cpp DataTreeCore.cpp JSONparseCore.cpp CharBufferCore.cpp LiteProtocolCore.cpp +ADD_LIBRARY(redAcore TimingCore.cpp DateTimeCore.cpp LogCore.cpp SignalCore.cpp DataTreeCore.cpp JSONparseCore.cpp CharBufferCore.cpp + LiteProtocolCore.cpp ItemBufferCore.cpp ApplicationCore.cpp FunctionCore.cpp FileCore.cpp SelectCore.cpp SelectableCore.cpp WatchdogCore.cpp DeviceCore.cpp ) diff --git a/FunctionCore-ChannelBuffer.h b/FunctionCore-ChannelBuffer.h new file mode 100644 index 0000000..694d212 --- /dev/null +++ b/FunctionCore-ChannelBuffer.h @@ -0,0 +1,222 @@ +/* + * FunctionCore.h + * + * Created on: 18 May 2016 + * Author: wentzelc + */ + +#ifndef REDACORE_FUNCTIONCORE_H_ +#define REDACORE_FUNCTIONCORE_H_ + +// Standard C/C++ Libraries +/* none */ + +// redA Libraries +#include "LogCore.h" +#include "DataTreeCore.h" +#include "CharBufferCore.h" +#include "ItemBufferCore.h" + +//--------------------------------------------------------------------------- + +// Preview +typedef struct SChannel TChannel; +typedef struct SChannelLink TChannelLink; +typedef struct SProcessBuffer TProcessBuffer; +typedef struct SProcessItem TProcessItem; + +class CFunctionCore; + +//--------------------------------------------------------------------------- + +struct SChannel +{ + char * Name; + + TChannelLink * FirstInput; + TChannelLink * FirstOutput; + + bool InputEnabled; + bool OutputEnabled; + + TProcessBuffer * InputBuffer; + + TChannel * Next; +}; +//--------------------------------------------------------------------------- + +struct SChannelLink +{ + CFunctionCore * Function; + char * Name; + + SChannelLink * Next; +}; +//--------------------------------------------------------------------------- + +struct SProcessBuffer +{ + // Process buffer + char * Name; // Name of buffer; + CItemBufferCore Buffer; // Message buffer + unsigned long LastRefNo; // Last RefNo for item + + // Input parameters + bool PassthroughCallback; // Send Callback once processed message has been passed on, else once processed + + // Output parameters + TChannel * OutputChannel; // Channel to which to pass buffer output + bool OutputCallback; // Expect callback on output? + + TProcessBuffer * Next; // Next buffer in list +}; +//--------------------------------------------------------------------------- + +struct SProcessItem +{ + // Input Parameters + TChannel * SourceChannel; + char * SourceRef; + bool SourceCallback; + + // Processing Parameters + bool Processed; + bool Completed; + + // Output Parameters + timeval CallbackTimer; + TChannelLink FirstOutput; + + // Input Data + void * DataIn; + int DataInLen; + + // Output Data + void * DataOut; + int DateOutLen; +}; +//--------------------------------------------------------------------------- + +class CFunctionCore +{ +protected: + // Function Definition + char * Name; + char * Type; + + // Configuration + CDataTree * DataTree; + TDataMember * ConfigMember; + TDataMember * LinkConfigMember; + + // Channels + TChannel * FirstChannel; + + // Processing Queues + TProcessBuffer * FirstProcessBuffer; + + // Logging + CLogCore * Log; + EDebugLevel LogLevel; + int LogOutput; + + // Stored Output + char * StoredOutput; + int StoredOutputLen; + + // Manage Channel + inline TChannel * GetChannel( const char * Name ) { + if (!Name) return NULL; + TChannel * Channel = FirstChannel; + while (Channel && strcmp( Name, Channel->Name )) + Channel = Channel->Next; + return Channel; + } + + // Load configuration + virtual bool LoadConfigData(); + virtual bool LoadChannelLinkData(); + + // Data Input/Output + virtual int Output( const TChannel * Channel, const char * Data, int Len ); + virtual bool PullInput( TChannel * Channel ); + + // Processing Queue + TProcessItem * CreateProcessItem(); + +public: + // Life cycle + CFunctionCore( const char * pName, const char * Type ); + virtual ~CFunctionCore(); + + // Load Configuration + virtual bool Init(); + + bool InitConfig( const char * pConfigPath ); + bool InitConfig( TDataMember * pConfigMember ); + + bool InitChannelLinks( const char * pLinkConfigPath ); + bool InitChannelLinks( TDataMember *pLinkConfigMember ); + + // Set Parameters Manually + bool SetLogParam( EDebugLevel pDebugLevel, int pOutputDisplay ); + bool SetLogLevel( EDebugLevel pDebugLevel ); + + // Miscellaneous + inline const char * GetName() { return Name; }; + inline const char * GetType() { return Type; }; + + // Manage Channels + virtual TChannel * AddChannel( const char * ChannelName, const bool pInputEnable = true, const bool pOutputEnabled = true ); + inline bool SetChannelOutEnable( const char * ChannelName, const bool pOutputEnable ) { + TChannel * Channel = GetChannel( ChannelName ); + if (!Channel) return false; + Channel->OutputEnabled = pOutputEnable; + return true; + } + inline bool SetChannelInEnable( const char * ChannelName, const bool pInputEnable ) { + TChannel * Channel = GetChannel( ChannelName ); + if (!Channel) return false; + Channel->InputEnabled = pInputEnable; + return true; + } + inline bool isInputEnabled( const char * ChannelName ) { + TChannel * Channel = GetChannel( ChannelName ); + return ((Channel)? Channel->InputEnabled : false); + } + inline bool isOutputEnabled( const char * ChannelName ) { + TChannel * Channel = GetChannel( ChannelName ); + return ((Channel)? Channel->OutputEnabled : false); + } + + // Pushing Data Output -> Input + virtual int Output( const char * ChannelName, const char * Data, int Len = -1 ); + virtual int Input( const char * ChannelName, const char * Data, int Len = -1 ); + + // Pulling Data Input <- Output + virtual bool PullInput( const char * ChannelName ); + virtual bool PullOutput( const char * ChannelName, char ** Data, int * Len = NULL ); + + // Manages Process Buffers + TProcessBuffer * CreateProcessBuffer( const char * Name ); + TProcessBuffer * GetProcessBuffer( const char * Name ); + + TProcessItem * CreateProcessItem( const char * BufferName ); + TProcessItem * GetProcessItem( const char BufferName, const int Ref ); + bool DestroyProcessItem( const char * BufferName, const int Ref ); + + // Queued Output + virtual bool OutputMessage( TChannel * SourceChannel, const char * TargetChannelName, const int RefNo, bool Callback, const char * Data, int Len = -1 ); + virtual bool OutputMessageCallback( TChannel * SourceChannel, const char * TargetChannelName, const int RefNo, const bool Success, const char * Error ); + virtual bool InputMessage( TChannel * SourceChannel, const char * TargetChannelName, const int RefNo, bool Callback, const char * Data, int Len = -1 ); + virtual bool InputMessageCancel( TChannel * SourceChannel, const char * TargetChannelName, const int RefNo ); + + // Automated Data Input/Output + virtual bool LinkInputChannel( const char * ChannelName, const char * OutFunctionName, const char * OutChannelName, bool Bidirectional ); + virtual bool LinkOutputChannel( const char * ChannelName, const char * InFunctionName, const char * InChannelName, bool Bidirectional ); + virtual bool Process() = 0; +}; + +//--------------------------------------------------------------------------- + +#endif /* REDACORE_FUNCTIONCORE_H_ */ diff --git a/FunctionCore.cpp b/FunctionCore.cpp index bc00f5a..e9f336f 100644 --- a/FunctionCore.cpp +++ b/FunctionCore.cpp @@ -42,7 +42,7 @@ CFunctionCore::CFunctionCore( const char * pName, const char * pType ) } // Channels - FirstChannel = NULL; + FirstChannel = NULL; // List Application->AddFunction( this ); @@ -52,10 +52,14 @@ CFunctionCore::CFunctionCore( const char * pName, const char * pType ) ConfigMember = NULL; LinkConfigMember = NULL; - // Output + // Logging Log = Application->Log; LogLevel = dlNone; LogOutput = OUT_NORMAL; + + // Stored output + StoredOutput = NULL; + StoredOutputLen = 0; } //--------------------------------------------------------------------------- @@ -411,7 +415,7 @@ bool CFunctionCore::LinkOutputChannel( const char * ChannelName, const char * In //--------------------------------------------------------------------------- // Manual Data Input/Output -int CFunctionCore::Input( const char * ChannelName, const char * Data, int MaxLen ) +int CFunctionCore::Input( const char * ChannelName, const char * Data, int Len ) { TChannel * Channel = NULL; @@ -433,11 +437,11 @@ int CFunctionCore::Input( const char * ChannelName, const char * Data, int MaxLe } else { // Return processed bytes - if (MaxLen == -1) { - MaxLen = strlen( Data ); + if (Len == -1) { + Len = strlen( Data ); } - if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, MaxLen, "%s: Channel '%s' - IN:", Name, ChannelName ); - return MaxLen; + if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, Len, "%s: Channel '%s' - IN:", Name, ChannelName ); + return Len; } } //--------------------------------------------------------------------------- @@ -495,3 +499,92 @@ int CFunctionCore::Output( const TChannel * Channel, const char * Data, int Len return Len; } //--------------------------------------------------------------------------- + +bool CFunctionCore::PullInput( const char * ChannelName ) +{ + TChannel * Channel = NULL; + + // Validate + if (!ChannelName) { + return false; + } + + // Get Channel + if (!(Channel = GetChannel( ChannelName ))) { + // Channel not found + if (Log) Log->Message( LogLevel, dlHigh, "%s: Channel '%s' - Input failed, Channel not found", Name, ChannelName ); + return false; + } + else { + // Return success + return PullInput( Channel ); + } +} +//--------------------------------------------------------------------------- + +bool CFunctionCore::PullInput( TChannel * Channel ) +{ + TChannelLink * InChannel = NULL; + char ** Data = NULL; + int * Len = NULL; + + // Validate + if (!Channel) { + return false; + } + + // Check if enabled + if (!Channel->InputEnabled) { + if (Log) Log->Message( LogLevel, dlHigh, "%s: Channel '%s' - Input failed, Channel input disabled", Name, Channel->Name ); + return false; + } + + // Pass output to all linked inputs + InChannel = Channel->FirstInput; + while (InChannel) + { + // Pull Output from Channel + if (InChannel->Function->PullOutput( InChannel->Name, Data, Len )) + { + // Use input + Input( Channel->Name, *Data, ((*Len)? *Len : -1) ); + } + InChannel = InChannel->Next; + } + + // Return success + return Len; +} +//--------------------------------------------------------------------------- + +bool CFunctionCore::PullOutput( const char * ChannelName, char ** Data, int * Len ) +{ + TChannel * Channel = NULL; + int TempLen = 0; + + // Validate + if (!ChannelName || !Data) { + return 0; + } + + // Get Channel + if (!(Channel = GetChannel( ChannelName ))) { + // Channel not found + if (Log) Log->Message( LogLevel, dlHigh, "%s: Channel '%s' - Output failed, Channel not found", Name, ChannelName ); + return 0; + } + else if (!Channel->InputEnabled) { + // Channel disabled + if (Log) Log->Message( LogLevel, dlHigh, "%s: Channel '%s' - Output failed, Channel output disabled", Name, ChannelName ); + return 0; + } + else { + // Return processed bytes + *Data = StoredOutput; + TempLen = (*Data)? strlen(*Data) : 0; + if (Len) *Len = TempLen; + if (Log) Log->Output( LogLevel, dlHigh, LogOutput, ((*Data)? *Data : "(NULL)"), TempLen, "%s: Channel '%s' - IN:", Name, ChannelName ); + return Len; + } +} +//--------------------------------------------------------------------------- diff --git a/FunctionCore.h b/FunctionCore.h index 448a2b7..2194914 100644 --- a/FunctionCore.h +++ b/FunctionCore.h @@ -14,8 +14,6 @@ // redA Libraries #include "LogCore.h" #include "DataTreeCore.h" -#include "CharBufferCore.h" - //--------------------------------------------------------------------------- @@ -65,11 +63,15 @@ protected: // Channels TChannel * FirstChannel; - // Output + // Logging CLogCore * Log; EDebugLevel LogLevel; int LogOutput; + // Stored Output + char * StoredOutput; + int StoredOutputLen; + // Manage Channel inline TChannel * GetChannel( const char * Name ) { if (!Name) return NULL; @@ -83,8 +85,9 @@ protected: virtual bool LoadConfigData(); virtual bool LoadChannelLinkData(); - // Manual Data Input/Output - virtual int Output( const TChannel * Channel, const char * Data, int Len ); + // Data Input/Output + virtual int Output( const TChannel * Channel, const char * Data, int Len ); + virtual bool PullInput( TChannel * Channel ); public: // Life cycle @@ -131,9 +134,13 @@ public: return ((Channel)? Channel->OutputEnabled : false); } - // Manual Data Input/Output - virtual int Input( const char * ChannelName, const char * Data, int MaxLen = -1 ); + // Pushing Data Output -> Input virtual int Output( const char * ChannelName, const char * Data, int Len = -1 ); + virtual int Input( const char * ChannelName, const char * Data, int Len = -1 ); + + // Pulling Data Input <- Output + virtual bool PullInput( const char * ChannelName ); + virtual bool PullOutput( const char * ChannelName, char ** Data, int * Len = NULL ); // Automated Data Input/Output virtual bool LinkInputChannel( const char * ChannelName, const char * OutFunctionName, const char * OutChannelName, bool Bidirectional ); diff --git a/ItemBufferCore.cpp b/ItemBufferCore.cpp new file mode 100644 index 0000000..1a4887c --- /dev/null +++ b/ItemBufferCore.cpp @@ -0,0 +1,188 @@ +/* + * BufferCore.h + * + * Created on: 22 July 2017 + * Author: wentzelc + */ + +// Standard C/C++ Libraries +#include +#include + +// redA Libraries +#include "ItemBufferCore.h" + +//--------------------------------------------------------------------------- + +//***** Function Prototypes *****// + +CItemBufferCore::CItemBufferCore( bool pCopyEntries ) +{ + // Parameters + CopyEntries = pCopyEntries; + + // Clear Event list + FirstItem = NULL; + LastItem = &FirstItem; +} +//--------------------------------------------------------------------------- + +CItemBufferCore::~ CItemBufferCore() +{ + // Free Event List + DeleteAll(); +} +//--------------------------------------------------------------------------- + +TBufferItem * CItemBufferCore::CreateItem( void * Entry, int Size ) +{ + TBufferItem * BufferItem; + + // Create structure + if (!(BufferItem = (TBufferItem *)calloc( sizeof(TBufferItem), 1 ))) + return NULL; + + // Create Entry + BufferItem->Size = Size; + if (CopyEntries) + { + // Create copy + if ((BufferItem->Entry = (void *)malloc( sizeof(char)*Size ))) { + // Copy Value + memcpy( BufferItem->Entry, Entry, Size ); + } + else { + // Fail + free( BufferItem ); + return NULL; + } + } + else + { + // Use pointer as is + BufferItem->Entry = Entry; + } + + // Return empty structure + return BufferItem; +} +//--------------------------------------------------------------------------- + +bool CItemBufferCore::DestroyItem( TBufferItem ** BufferItem ) +{ + // Check if valid pointer + if (!BufferItem || !*BufferItem) + return false; + + // Destroy pointers + if (CopyEntries && (*BufferItem)->Entry) + DestroyEntry( &((*BufferItem)->Entry) ); + + // Destroy structure + free( *BufferItem ); + *BufferItem = NULL; + + return true; +} +//--------------------------------------------------------------------------- + +bool CItemBufferCore::DestroyEntry( void ** Entry ) +{ + // Verify pointer + if (!Entry || !*Entry) + return false; + + // free & clear memory + free( *Entry ); + *Entry = NULL; + + return true; +} +//--------------------------------------------------------------------------- + +bool CItemBufferCore::Push( void * Entry, int Size ) +{ + // Verify pointer + if (!Entry || !Size) + return false; + + // Try to create an add item to list + if (!(*LastItem = CreateItem( Entry, Size ))) + return false; + + // Move Next entry reference + LastItem = &((*LastItem)->NextItem); + return true; +} +//--------------------------------------------------------------------------- + +void * CItemBufferCore::Pop( int * Size ) +{ + void * Entry; + + // Return entry + if ((Entry = Peek( Size ))) { + Delete(); + } + + // return event + return Entry; +} +//--------------------------------------------------------------------------- + +void * CItemBufferCore::Peek( int * Size ) +{ + void * Entry; + + // Check if any events available + if (!FirstItem) { + if (Size) *Size = 0; + return NULL; + } + + // Get entry and size + Entry = FirstItem->Entry; + if (Size) *Size = FirstItem->Size; + + // return event + return Entry; +} +//--------------------------------------------------------------------------- + +bool CItemBufferCore::Delete() +{ + TBufferItem * BufferItem; + + // check if buffer empty + if (!FirstItem) + return false; + + // Delete event from list + BufferItem = FirstItem; + FirstItem = FirstItem->NextItem; + + // Check if last event pointer still correct + if (!FirstItem) + LastItem = &FirstItem; + + // Destroy entry and holder + if (CopyEntries) + DestroyEntry( &(BufferItem->Entry) ); + free( BufferItem ); + + return true; +} +//--------------------------------------------------------------------------- + +void CItemBufferCore::DeleteAll() +{ + TBufferItem * NextItem; + + while (FirstItem) + { + NextItem = FirstItem->NextItem; + DestroyItem( &FirstItem ); + FirstItem = NextItem; + } +} +//--------------------------------------------------------------------------- diff --git a/ItemBufferCore.h b/ItemBufferCore.h new file mode 100644 index 0000000..569b513 --- /dev/null +++ b/ItemBufferCore.h @@ -0,0 +1,66 @@ +/* + * BufferCore.h + * + * Created on: 22 July 2017 + * Author: wentzelc + */ + +#ifndef REDACORE_ITEMBUFFERCORE_H_ +#define REDACORE_ITEMBUFFERCORE_H_ + +// Standard C/C++ Libraries +#include + +// redA Libraries +/* none */ + +//--------------------------------------------------------------------------- + +//***** Data Structures *****// + +typedef struct SBufferItem TBufferItem; + +struct SBufferItem { + void * Entry; + int Size; + + TBufferItem * NextItem; +}; + +//--------------------------------------------------------------------------- + +//***** Function Prototypes *****// + +class CItemBufferCore +{ + protected: + // Parameters + bool CopyEntries; // Make copies of entries and destroy them when done? + + // Events + TBufferItem * FirstItem; + TBufferItem ** LastItem; + + // Item Life cycle + TBufferItem * CreateItem( void * Entry, int Size ); + bool DestroyItem( TBufferItem ** BufferItem ); + + virtual bool DestroyEntry( void ** Entry ); + + public: + // Initiate object + CItemBufferCore( bool pCopyEntries ); + virtual ~CItemBufferCore(); + + // Buffer Operations + bool Push( void * Entry, int Size ); + void * Pop( int * Size = NULL ); + void * Peek( int * Size = NULL ); + bool Delete(); + void DeleteAll(); +}; + +//--------------------------------------------------------------------------- + +#endif /* REDACORE_ITEMBUFFERCORE_H_ */ +