/* * FunctionListCore.cpp * * Created on: 12 Jul 2017 * Author: wentzelc */ // redA Libraries #include "ApplicationCore.h" #include "WatchdogCore.h" #include "FileCore.h" // Standard C/C++ Libraries #include #include #include //--------------------------------------------------------------------------- // Global Vars extern char * ProcessName; //--------------------------------------------------------------------------- CApplication::CApplication( EDebugLevel pLogLevel ) { // Set signal handlers ConfigureSignalHandlers(); // Variables used for configuration ConfigMember = NULL; FunctionConfigMember = NULL; LinkConfigMember = NULL; ConfigFile = NULL; AddressFile = NULL; // Create output logger Log = new CLogCore( stdout ); LogLevel = pLogLevel; LogOutput = OUT_NORMAL; // Create Configuration DataTree = new CDataTree(); ConfigParser = new CJSONparse( DataTree ); // Selector Selector = NULL; // List FirstFunction = NULL; } //--------------------------------------------------------------------------- CApplication::~CApplication() { TFunctionItem * NextFunction; if (FirstFunction) { // Show Start of termination if (Log) Log->Message( dlLow, dlLow, "%s: Terminating...", ProcessName ); // Destroy functions while (FirstFunction) { NextFunction = FirstFunction->Next; delete( FirstFunction->Function ); free( FirstFunction ); FirstFunction = NextFunction; } } // Show Completion if (Log) Log->Message( dlLow, dlLow, "%s: Terminated.", ProcessName ); // Destroy tools if (Selector) delete Selector; if (Log) delete Log; if (DataTree) delete DataTree; if (ConfigParser) delete ConfigParser; // Free Process Name if (ProcessName) free( ProcessName ); } //--------------------------------------------------------------------------- void CApplication::GetProcessName( char ** ProcessName, char * pFilePath ) { char * TempStr; // Remove Path TempStr = strrchr( pFilePath, '/' ); if (TempStr[0] == '/') TempStr++; // Copy Process Name *ProcessName = (char*)malloc( strlen(TempStr)+1 ); strcpy( *ProcessName, TempStr ); // Remove extension TempStr = strrchr( *ProcessName, '.' ); if (TempStr) TempStr[0] = 0; } //--------------------------------------------------------------------------- bool CApplication::LoadConfig( int argc, char *argv[], const char * pConfigPath ) { // Read Parameters if ((argc != 2)) { // Get Process Name GetProcessName( &ProcessName, argv[0] ); // Incorrect no of parameters, show correct usage printf( "%s: Incorrect number of parameters\n", ProcessName ); printf( " usage: %s [ConfigFile]\n\n", ProcessName ); return false; } else { // Load parameters GetProcessName( &ProcessName, argv[1] ); ConfigFile = argv[1]; } // Load Application List if (ConfigParser->ReadFromFile( pConfigPath, ConfigFile )) { if (Log) Log->Message( dlLow, dlLow, "%s: Config file loaded (%s)", ProcessName, ConfigFile ); } else { if (Log) Log->Message( dlLow, dlLow, "%s: Fail to load config file (%s)- %s", ProcessName, ConfigFile, ConfigParser->GetError() ); return false; } //ConfigParser->WriteToScreen( pConfigPath, 2 ); // Loaded successfully return true; } //--------------------------------------------------------------------------- bool CApplication::SaveConfig() { // Save updated configuration if (ConfigFile && *ConfigFile) ConfigParser->WriteToFile( "config", ConfigFile ); if (AddressFile && *AddressFile ) ConfigParser->WriteToFile( "address", AddressFile ); return true; } //--------------------------------------------------------------------------- bool CApplication::LoadConfigData() { TDataMember * TempMember; EDebugLevel pLogLevel; int pLogOutput; char * TempStr; // Get debug level pLogLevel = dlNone; TempStr = (char*)DataTree->GetStr( ConfigMember, "Log/Level", "Medium", true ); if (TempStr) { if (!strcasecmp( TempStr, "Low" )) pLogLevel = dlLow; else if (!strcasecmp( TempStr, "Medium" )) pLogLevel = dlMedium; else if (!strcasecmp( TempStr, "High" )) pLogLevel = dlHigh; } // Set debug output pLogOutput = 0; TempMember = DataTree->GetFirstChild( ConfigMember, "Log/Output", true ); while (TempMember) { if (TempMember->Value) { if (!strcasecmp( TempMember->Value, "Normal")) pLogOutput |= OUT_NORMAL; else if (!strcasecmp( TempMember->Value, "Bin")) pLogOutput |= OUT_BIN; else if (!strcasecmp( TempMember->Value, "Hex")) pLogOutput |= OUT_HEX; else if (!strcasecmp( TempMember->Value, "Count")) pLogOutput |= OUT_COUNT; else if (!strcasecmp( TempMember->Value, "AsIs")) pLogOutput |= OUT_ASIS; else if (!strcasecmp( TempMember->Value, "CRLF")) pLogOutput |= OUT_CRLF; } // Next TempMember = DataTree->GetNextChild( TempMember ); } SetLogParam( pLogLevel, pLogOutput ); // Load Address List if ((AddressFile = (char*)DataTree->GetStr( ConfigMember, "AddressList/Path", NULL ))) { if (ConfigParser->ReadFromFile( "address", AddressFile )) { if (Log) Log->Message( dlLow, dlLow, "%s: Address file loaded (%s)", ProcessName, AddressFile ); } else { if (Log) Log->Message( dlLow, dlLow, "%s: Fail to load Address file (%s) - %s", ProcessName, AddressFile, ConfigParser->GetError() ); } //ConfigParser->WriteToScreen( pAddressListPath, 2 ); } // Configure Selector if ((TempMember = DataTree->GetMember( ConfigMember, "Selector" ))) { // Create Selector Selector = new CSelect( (int)DataTree->GetInt( TempMember, "Wait", 5, true ), LogLevel ); } return true; } //--------------------------------------------------------------------------- bool CApplication::SetLogParam( EDebugLevel pDebugLevel, int pOutputDisplay ) { // Output LogLevel = pDebugLevel; LogOutput = pOutputDisplay; return true; } //--------------------------------------------------------------------------- bool CApplication::Init() { // Report status if (Log) Log->Message( LogLevel, dlLow, "%s: Application Initialised", ProcessName ); return true; } //--------------------------------------------------------------------------- bool CApplication::InitConfig( const char * pConfigPath ) { // Check if Datatree exists if (!DataTree || !(ConfigMember = DataTree->GetMember( NULL, pConfigPath ))) { return false; } // LoadConfiguration LoadConfigData(); Init(); return true; } //--------------------------------------------------------------------------- bool CApplication::InitFunctions( const char * pConfigPath ) { CFunctionCore * Function; TDataMember * TempMember; char * Type; // Check of path exists if (!DataTree || !(FunctionConfigMember = DataTree->GetMember( NULL, pConfigPath ))) return false; // Process each Channel TempMember = DataTree->GetFirstChild( FunctionConfigMember ); while (TempMember) { // Get function parameters Type = (char*)DataTree->GetStr( TempMember, "Type", "Custom", true ); // Get or create function if (!strcasecmp( Type, "WatchdogClient" )) { Function = new CWatchdogCore( TempMember->Name ); } else if (!strcasecmp( Type, "Selectable" )) { Function = new CSelectableCore( TempMember->Name ); } else if (!strcasecmp( Type, "File" )) { Function = new CFileCore( TempMember->Name ); } else { Function = GetFunction( TempMember->Name ); } // Load Function configuration and Initialise if (Function) { Function->InitConfig( TempMember ); } // Next TempMember = TempMember->Next; } return true; } //--------------------------------------------------------------------------- bool CApplication::InitFunctionLinks( const char * pConfigPath ) { TFunctionItem * FunctionItem; TDataMember * TempMember; // Check of path exists if (!DataTree || !(LinkConfigMember = DataTree->GetMember( NULL, pConfigPath ))) return false; // Process each Channel FunctionItem = FirstFunction; while (FunctionItem) { // Build links for function if ((TempMember = DataTree->GetMember( LinkConfigMember, FunctionItem->Function->GetName() ))) FunctionItem->Function->InitChannelLinks( TempMember ); // Next FunctionItem = FunctionItem->Next; } return true; } //--------------------------------------------------------------------------- // Build List bool CApplication::AddFunction( CFunctionCore * Function ) { TFunctionItem ** FunctionPtr; // Check if unique, else get end of list FunctionPtr = &FirstFunction; while (*FunctionPtr && strcasecmp( (*FunctionPtr)->Function->GetName(), Function->GetName() )) FunctionPtr = &((*FunctionPtr)->Next); // Check if exists if (*FunctionPtr) return false; // Add to end of list *FunctionPtr = (TFunctionItem*)calloc( sizeof(TFunctionItem), 1 ); (*FunctionPtr)->Function = Function; return true; } //--------------------------------------------------------------------------- // Search List CFunctionCore * CApplication::GetFunction( const char * Name ) { TFunctionItem * FunctionItem; // Find in list FunctionItem = FirstFunction; while (FunctionItem && strcasecmp( FunctionItem->Function->GetName(), Name )) FunctionItem = FunctionItem->Next; return ((FunctionItem)? FunctionItem->Function : NULL); } //--------------------------------------------------------------------------- bool CApplication::Run() { TFunctionItem * FunctionItem; // Check for FD Events/States if (Selector) { Selector->Test(); } // Process Functions for (FunctionItem = FirstFunction; FunctionItem; FunctionItem = FunctionItem->Next ) FunctionItem->Function->Process(); return true; } //---------------------------------------------------------------------------