Major Update:

- Implement consistent Function addition to application
  - Use TYPE_XXX constants to declare function type
  - Use NewXXXX() methods to call constructor correctly
  - Add FunctionType list (with constructor) to Application
  - Create Function by comparison to FunctionType list
- Simplify LoadConfig() and Init() methods for functions
  - Combine methods into Init() method
  - Pass relevant data member to Init() method
  - Remove all CDataMember references on functions
- ApplicationCore:
  - Split ReadParam() method from LoadConfig() method
  - Split main configuration into separate files:
    - config/ - main config file, general application settings
    - definition/ - application definition, e.g. function blocks
  - Definition and Address List files specified in config file
  - Load address file in address/ branch
  - Made DataTree & JSONparser private
  - Made Config, Definition & Address branches public
  - Removed unnecessary branch references
  - Improved event logging
- DataTreeCore:
  - Allow GetChFirstChild & GetChElement to create parent branches
    with correct type, ie. Object/Array
  - Remove unnecessary Create param from GetXxx functions
  - Bug fix: Print empty objects/arrays correct, ie. empty brackets
  - Bug fix: Adding element at specific index
  - Bug fix: Error when get/create string value with "null"
- FunctionCore:
  - Type param now set as constant via constructor
  - Create empty Handles & Channels objects if none in Config
- SelectableCore:
  - Add Queue length parameter to handles for UNIX and TCP sockets
- DeviceCore:
  - Bug fix: missing Process() method
This commit is contained in:
Charl Wentzel
2018-11-24 13:35:23 +02:00
parent 7434334280
commit a972fb9101
15 changed files with 518 additions and 469 deletions

View File

@@ -12,6 +12,7 @@
#include "ApplicationCore.h"
#include "WatchdogCore.h"
#include "FileCore.h"
#include "DeviceCore.h"
//---------------------------------------------------------------------------
@@ -25,13 +26,9 @@ CApplication::CApplication( EDebugLevel pLogLevel )
// Set signal handlers
ConfigureSignalHandlers();
// Variables used for configuration
ConfigMember = NULL;
FunctionConfigMember = NULL;
LinkConfigMember = NULL;
ConfigFile = NULL;
AddressFile = NULL;
DefinitionFile = NULL;
ConfigFile = NULL;
AddressFile = NULL;
// Create output logger
Log = new CLogCore( stdout );
@@ -39,31 +36,49 @@ CApplication::CApplication( EDebugLevel pLogLevel )
LogOutput = OUT_NORMAL;
// Create Configuration
DataTree = new CDataMember();
JSONparser = new CJSONparse( DataTree );
DataTree = new CDataMember();
Config = DataTree->GetChild( "Config", true );
Definition = DataTree->GetChild( "Definition", true );
AddressList = DataTree->GetChild( "AddressList", true );
JSONparser = new CJSONparse( DataTree );
// Selector
Selector = NULL;
Selector = NULL;
// List
FirstFunction = NULL;
FirstFunctionType = NULL;
FirstFunction = NULL;
// Add Core Function Types
//AddFunctionType( TYPE_FUNCTION, NewFunctionCore ); // <-- Can't add virtual function
AddFunctionType( TYPE_SELECTABLE, NewSelectableCore );
AddFunctionType( TYPE_WATCHDOG, NewWatchdogCore );
AddFunctionType( TYPE_FILE, NewFileCore );
//AddFunctionType( TYPE_DEVICE, NewDeviceCore ); // <-- Can't add virtual function
}
//---------------------------------------------------------------------------
CApplication::~CApplication()
{
TFunctionItem * NextFunction;
TFunctionType * NextType;
if (FirstFunction)
// Destroy functions
while (FirstFunction)
{
// Destroy functions
while (FirstFunction)
{
NextFunction = FirstFunction->Next;
delete( FirstFunction->Function );
free( FirstFunction );
FirstFunction = NextFunction;
}
NextFunction = FirstFunction->Next;
delete( FirstFunction->Function );
free( FirstFunction );
FirstFunction = NextFunction;
}
// Destroy function types
while (FirstFunctionType)
{
NextType = FirstFunctionType->Next;
free( FirstFunctionType->Name );
free( FirstFunctionType );
FirstFunctionType = NextType;
}
// Show Completion
@@ -98,7 +113,7 @@ void CApplication::GetProcessName( char ** ProcessName, char * pFilePath )
}
//---------------------------------------------------------------------------
bool CApplication::LoadConfig( int argc, char *argv[], const char * pConfigPath )
bool CApplication::ReadParam( int argc, char *argv[] )
{
// Read Parameters
if ((argc != 2))
@@ -116,16 +131,49 @@ bool CApplication::LoadConfig( int argc, char *argv[], const char * pConfigPath
// Load parameters
GetProcessName( &ProcessName, argv[1] );
ConfigFile = argv[1];
return true;
}
}
//---------------------------------------------------------------------------
// Load Application List
if (JSONparser->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, JSONparser->GetError() );
bool CApplication::LoadConfig()
{
// Load Configuration Data
if (!JSONparser->ReadFromFile( "Config", ConfigFile )) {
if (Log) Log->Message( dlLow, dlLow, "%s: Fail to load Configuration file (%s)- %s", ProcessName, ConfigFile, JSONparser->GetError() );
return false;
}
//JSONparser->WriteToScreen( pConfigPath, 2 );
else {
//JSONparser->WriteToScreen( "config", 2 );
if (Log) Log->Message( dlLow, dlLow, "%s: Configuration file loaded (%s)", ProcessName, ConfigFile );
}
// Load Application Definition
if (!(DefinitionFile = (char*)Config->GetChStr( "DefinitionFile" ))) {
if (Log) Log->Message( dlLow, dlLow, "%s: No Application Definition file specified", ProcessName );
return false;
}
else if (!JSONparser->ReadFromFile( "Definition", DefinitionFile )) {
if (Log) Log->Message( dlLow, dlLow, "%s: Fail to load Application Definition file (%s)- %s", ProcessName, DefinitionFile, JSONparser->GetError() );
return false;
}
else {
//JSONparser->WriteToScreen( "application", 2 );
if (Log) Log->Message( dlLow, dlLow, "%s: Application Definition file loaded (%s)", ProcessName, DefinitionFile );
}
// Load Address List
if (!(AddressFile = (char*)Config->GetChStr( "AddressFile" ))) {
if (Log) Log->Message( dlLow, dlLow, "%s: No Address List file specified", ProcessName );
}
else if (!JSONparser->ReadFromFile( "AddressList", AddressFile )) {
if (Log) Log->Message( dlLow, dlLow, "%s: Fail to load Address List file (%s)- %s", ProcessName, AddressFile, JSONparser->GetError() );
return false;
}
else {
//JSONparser->WriteToScreen( "address", 2 );
if (Log) Log->Message( dlLow, dlLow, "%s: Address List file loaded (%s)", ProcessName, AddressFile );
}
// Loaded successfully
return true;
@@ -136,79 +184,11 @@ bool CApplication::SaveConfig()
{
// Save updated configuration
if (ConfigFile && *ConfigFile)
JSONparser->WriteToFile( "config", ConfigFile );
JSONparser->WriteToFile( "Config", ConfigFile );
if (DefinitionFile && *DefinitionFile)
JSONparser->WriteToFile( "Definition", DefinitionFile );
if (AddressFile && *AddressFile )
JSONparser->WriteToFile( "address", AddressFile );
return true;
}
//---------------------------------------------------------------------------
bool CApplication::LoadConfigData()
{
CDataMember * TempMember;
EDebugLevel pLogLevel;
int pLogOutput;
char * TempStr;
// Get debug level
pLogLevel = dlNone;
TempStr = (char*)ConfigMember->GetChStr( "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;
if ((TempMember = ConfigMember->GetChild( "Log/Output", true )))
{
TempMember = TempMember->GetFirstChild();
while (TempMember)
{
if ((TempStr = (char*)TempMember->GetStr()))
{
if (!strcasecmp( TempStr, "Normal"))
pLogOutput |= OUT_NORMAL;
else if (!strcasecmp( TempStr, "Bin"))
pLogOutput |= OUT_BIN;
else if (!strcasecmp( TempStr, "Hex"))
pLogOutput |= OUT_HEX;
else if (!strcasecmp( TempStr, "Count"))
pLogOutput |= OUT_COUNT;
else if (!strcasecmp( TempStr, "AsIs"))
pLogOutput |= OUT_ASIS;
else if (!strcasecmp( TempStr, "CRLF"))
pLogOutput |= OUT_CRLF;
}
// Next
TempMember = TempMember->GetNextPeer();
}
}
SetLogParam( pLogLevel, pLogOutput );
// Load Address List
if ((AddressFile = (char*)ConfigMember->GetChStr( "AddressList/Path", NULL )))
{
if (JSONparser->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, JSONparser->GetError() );
}
//JSONparser->WriteToScreen( pAddressListPath, 2 );
}
// Configure Selector
if ((TempMember = ConfigMember->GetChild( "Selector" )))
{
// Create Selector
Selector = new CSelect( (int)TempMember->GetChInt( "Wait", 5, true ), LogLevel );
}
JSONparser->WriteToFile( "AddressList", AddressFile );
return true;
}
//---------------------------------------------------------------------------
@@ -223,117 +203,220 @@ bool CApplication::SetLogParam( EDebugLevel pDebugLevel, int pOutputDisplay )
}
//---------------------------------------------------------------------------
bool CApplication::Init()
bool CApplication::InitApplication()
{
// Report status
if (Log) Log->Message( LogLevel, dlLow, "%s: Application Initialised", ProcessName );
CDataMember * CoreConfig;
CDataMember * ItemConfig;
CDataMember * SelectConfig;
EDebugLevel pLogLevel;
int pLogOutput;
char * TempStr;
return true;
}
//---------------------------------------------------------------------------
// Get Core definition
CoreConfig = Definition->GetChild( "Core", true );
bool CApplication::InitConfig( const char * pConfigPath )
{
// Check if Datatree exists
if (!DataTree || !(ConfigMember = DataTree->GetChild( pConfigPath ))) {
return false;
// Get debug level
pLogLevel = dlNone;
TempStr = (char*)CoreConfig->GetChStr( "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;
}
// LoadConfiguration
LoadConfigData();
Init();
// Set debug output
pLogOutput = 0;
ItemConfig = CoreConfig->GetChild( "Log/Output[0]", true ); // Create first element if not exist
while (ItemConfig)
{
if ((TempStr = (char*)ItemConfig->GetStr( "Normal" ))) // Set default value "Normal" if not set
{
if (!strcasecmp( TempStr, "Normal")) // Normal ASCII -> Unless "AsIs", print special chars as "."
pLogOutput |= OUT_NORMAL;
else if (!strcasecmp( TempStr, "Bin")) // Print as Binary value ('1' and '0')
pLogOutput |= OUT_BIN;
else if (!strcasecmp( TempStr, "Hex")) // Print as Hexadecimal value (0-9,A-F)
pLogOutput |= OUT_HEX;
else if (!strcasecmp( TempStr, "Count")) // Print number of characters
pLogOutput |= OUT_COUNT;
else if (!strcasecmp( TempStr, "AsIs")) // Use with "Normal" -> Do not print special chars as "."
pLogOutput |= OUT_ASIS;
else if (!strcasecmp( TempStr, "CRLF")) // Add \r\n at end of line if not present
pLogOutput |= OUT_CRLF;
else
pLogOutput |= OUT_NORMAL;
}
ItemConfig = ItemConfig->GetNextPeer();
}
SetLogParam( pLogLevel, pLogOutput );
// Configure Selector
if ((SelectConfig = CoreConfig->GetChild( "Selector" ))) {
Selector = new CSelect( (int)SelectConfig->GetChInt( "Wait", 5, true ), LogLevel );
}
// Show status
if (Log) Log->Message( LogLevel, dlLow, "%s: Application Core configured.", ProcessName );
return true;
}
//---------------------------------------------------------------------------
bool CApplication::InitFunctions( const char * pConfigPath )
bool CApplication::InitFunction( CFunctionCore * Function )
{
char FunctionPath[100];
CDataMember * FunctionConfig = NULL;
// Validate
if (!Function)
return false;
// Load configuration
sprintf( FunctionPath, "FunctionBlocks/%s", Function->GetName() );
if (!(FunctionConfig = Definition->GetChild( FunctionPath, true ))) {
if (Log) Log->Message( LogLevel, dlMedium, "%s: Function '%s' - Type '%s' cannot create config!",
ProcessName, Function->GetName(), Function->GetType() );
}
// Configure Function
else if (!Function->Init( FunctionConfig )) {
if (Log) Log->Message( LogLevel, dlMedium, "%s: Function '%s' - Type '%s' init failed!",
ProcessName, Function->GetName(), Function->GetType() );
return false;
}
else {
if (Log) Log->Message( LogLevel, dlMedium, "%s: Function '%s' - Type '%s' configured.",
ProcessName, Function->GetName(), Function->GetType() );
}
return true;
}
//---------------------------------------------------------------------------
bool CApplication::InitFunctions()
{
CDataMember * FunctionList;
CDataMember * FunctionConfig;
CFunctionCore * Function;
CDataMember * TempMember;
char * Type;
// Check of path exists
if (!DataTree || !(FunctionConfigMember = DataTree->GetChild( pConfigPath )))
if (!(FunctionList = Definition->GetChild( "FunctionBlocks" ))) {
if (Log) Log->Message( LogLevel, dlLow, "%s: No Function Block specified", ProcessName );
return false;
}
// Process each Channel
TempMember = FunctionConfigMember->GetFirstChild();
while (TempMember)
FunctionConfig = FunctionList->GetFirstChild();
while (FunctionConfig)
{
// Get function parameters
Type = (char*)TempMember->GetChStr( "Type", "Custom", true );
Type = (char*)FunctionConfig->GetChStr( "Type", "Custom", true );
if (Log) Log->Message( LogLevel, dlLow, "%s: Function '%s' - Type '%s' initialising...",
ProcessName, FunctionConfig->GetName(), Type );
// Get or create function
if (!strcasecmp( Type, "WatchdogClient" )) {
Function = new CWatchdogCore( TempMember->GetName() );
}
else if (!strcasecmp( Type, "Selectable" )) {
Function = new CSelectableCore( TempMember->GetName() );
}
else if (!strcasecmp( Type, "File" )) {
Function = new CFileCore( TempMember->GetName() );
}
else {
Function = GetFunction( TempMember->GetName() );
}
Function = AddFunction( Type, FunctionConfig->GetName() );
// Load Function configuration and Initialise
if (Function) {
Function->InitConfig( TempMember );
if (!Function) {
if (Log) Log->Message( LogLevel, dlMedium, "%s: Function '%s' - Type '%s' not found!",
ProcessName, FunctionConfig->GetName(), Type );
}
else if (!Function->Init( FunctionConfig )) {
if (Log) Log->Message( LogLevel, dlMedium, "%s: Function '%s' - Type '%s' init failed!",
ProcessName, Function->GetName(), Function->GetType() );
}
else {
if (Log) Log->Message( LogLevel, dlMedium, "%s: Function '%s' - Type '%s' configured.",
ProcessName, Function->GetName(), Function->GetType() );
}
// Next
TempMember = TempMember->GetNextPeer();
FunctionConfig = FunctionConfig->GetNextPeer();
}
return true;
}
//---------------------------------------------------------------------------
bool CApplication::InitFunctionLinks( const char * pConfigPath )
bool CApplication::InitFunctionLinks()
{
CDataMember * LinkList;
CDataMember * LinkConfig;
TFunctionItem * FunctionItem;
CDataMember * TempMember;
// Check of path exists
if (!DataTree || !(LinkConfigMember = DataTree->GetChild( pConfigPath )))
if (!(LinkList = Definition->GetChild( "ChannelLinks", true ))) {
if (Log) Log->Message( LogLevel, dlMedium, "%s: No Function Channel links specified.", ProcessName );
return false;
}
else {
if (Log) Log->Message( LogLevel, dlLow, "%s: Linking Function Block Channels...", ProcessName );
}
// Process each Channel
FunctionItem = FirstFunction;
while (FunctionItem)
{
// Build links for function
if ((TempMember = LinkConfigMember->GetChild( FunctionItem->Function->GetName() )))
FunctionItem->Function->InitChannelLinks( TempMember );
if ((LinkConfig = LinkList->GetChild( FunctionItem->Function->GetName() )))
FunctionItem->Function->InitChannelLinks( LinkConfig );
// Next
FunctionItem = FunctionItem->Next;
}
if (Log) Log->Message( LogLevel, dlLow, "%s: Function Block Channels linked.", ProcessName );
return true;
}
//---------------------------------------------------------------------------
bool CApplication::AddFunctionType( const char * Type, FFuncConstructor Constructor )
{
TFunctionType ** FunctionType;
// Get end of list
FunctionType = &FirstFunctionType;
while (*FunctionType)
FunctionType = &((*FunctionType)->Next);
// Add new Type
*FunctionType = (TFunctionType*)calloc( sizeof(TFunctionType), 1 );
(*FunctionType)->Name = (char*)malloc( strlen(Type)+1 );
strcpy( (*FunctionType)->Name, Type );
(*FunctionType)->Constructor = Constructor;
return true;
};
//---------------------------------------------------------------------------
// Build List
bool CApplication::AddFunction( CFunctionCore * Function )
CFunctionCore * CApplication::AddFunction( const char * Type, const char * Name )
{
TFunctionItem ** FunctionPtr;
TFunctionType * FunctionType;
// Check if unique, else get end of list
FunctionPtr = &FirstFunction;
while (*FunctionPtr && strcasecmp( (*FunctionPtr)->Function->GetName(), Function->GetName() ))
while (*FunctionPtr && strcasecmp( (*FunctionPtr)->Function->GetName(), Name ))
FunctionPtr = &((*FunctionPtr)->Next);
if (*FunctionPtr) return NULL; // Can't overwrite existing function
// Check if exists
if (*FunctionPtr)
return false;
// Check if type is valid
FunctionType = FirstFunctionType;
while (FunctionType && strcasecmp( FunctionType->Name, Type ))
FunctionType = FunctionType->Next;
if (!FunctionType) return NULL; // Type not defined
// Add to end of list
*FunctionPtr = (TFunctionItem*)calloc( sizeof(TFunctionItem), 1 );
(*FunctionPtr)->Function = Function;
return true;
(*FunctionPtr)->Function = FunctionType->Constructor( Name );
return (*FunctionPtr)->Function;
}
//---------------------------------------------------------------------------

View File

@@ -23,16 +23,25 @@
//---------------------------------------------------------------------------
// Preview
typedef struct SFunctionItem TFunctionItem;
typedef struct SFunctionType TFunctionType;
typedef struct SFunctionItem TFunctionItem;
typedef CFunctionCore * (*FFuncConstructor)( const char * Name );
class Application;
//---------------------------------------------------------------------------
struct SFunctionType {
char * Name;
FFuncConstructor Constructor;
TFunctionType * Next;
};
//---------------------------------------------------------------------------
struct SFunctionItem
{
CFunctionCore * Function;
SFunctionItem * Next;
};
//---------------------------------------------------------------------------
@@ -42,50 +51,54 @@ class CApplication
protected:
// Variables used for configuration
char * ConfigFile;
char * DefinitionFile;
char * AddressFile;
// Configuration
CDataMember * DataTree;
CJSONparse * JSONparser = NULL;
// List
TFunctionType * FirstFunctionType;
TFunctionItem * FirstFunction;
// Output
EDebugLevel LogLevel;
int LogOutput;
// Configuration
CDataMember * ConfigMember;
CDataMember * FunctionConfigMember;
CDataMember * LinkConfigMember;
bool LoadConfigData();
public:
// Public function vars
CDataMember * DataTree;
CLogCore * Log;
CSelect * Selector;
CJSONparse * JSONparser = NULL;
// Configuration
CDataMember * Config;
CDataMember * Definition;
CDataMember * AddressList;
// Life Cycle
CApplication( EDebugLevel pDebugLevel );
virtual ~CApplication();
// Manage Config File
bool ReadParam( int argc, char *argv[] );
void GetProcessName( char ** ProcessName, char * pFilePath );
bool LoadConfig( int argc, char *argv[], const char * pConfigPath );
bool LoadConfig();
bool SaveConfig();
// Manually set configuration
bool SetLogParam( EDebugLevel pDebugLevel, int pOutputDisplay );
// Init application
virtual bool Init();
bool InitConfig( const char * pConfigPath );
bool InitFunctions( const char * pConfigPath );
bool InitFunctionLinks( const char * pConfigPath );
bool InitApplication();
bool InitFunctions();
bool InitFunction( CFunctionCore * Function );
bool InitFunctionLinks();
// Manage Functions
bool AddFunction( CFunctionCore * Function );
bool AddFunctionType( const char * Type, FFuncConstructor Constructor );
CFunctionCore * AddFunction( const char * Type, const char * Name );
CFunctionCore * GetFunction( const char * Name );
// Run Application

View File

@@ -226,7 +226,7 @@ CDataMember * CDataMember::GetChild( const char * Path, bool Create )
// Create element if needed
if (!*Child && Create) {
if ((Index == -1) || (Index = Count + 1)) {
if ((Index == -1) || (Index == Count)) {
*Child = new CDataMember( Member, NULL );
}
}
@@ -271,35 +271,41 @@ CDataMember * CDataMember::GetChild( const char * Path, bool Create )
}
//---------------------------------------------------------------------------
CDataMember * CDataMember::GetChFirstChild( const char * Path )
CDataMember * CDataMember::GetChFirstChild( const char * Path, bool Create )
{
CDataMember * Member = NULL;
// Find member
Member = (!Path || !*Path)? this : GetChild( Path, false );
Member = (!Path || !*Path)? this : GetChild( Path, Create );
// Check if valid type
if (!Member || ((Member->Type != jtObject) && (Member->Type != jtNull))) {
return NULL;
}
else if (Create && (Member->Type == jtNull)) {
Member->SetObject(); // Set newly created member to object
}
return Member->FirstChild;
}
//---------------------------------------------------------------------------
CDataMember * CDataMember::GetChElement( const char * Path, const int Index )
CDataMember * CDataMember::GetChElement( const char * Path, const int Index, bool Create )
{
CDataMember * Member = NULL;
CDataMember * Child = NULL;
int Count;
// Find Member
Member = (!Path || !*Path)? this : GetChild( Path, false );
Member = (!Path || !*Path)? this : GetChild( Path, Create );
// Check if valid type
if (!Member || ((Member->Type != jtArray) && (Member->Type != jtNull))) {
return NULL;
}
else if (Create && (Member->Type == jtNull)) {
Member->SetArray(); // Set newly created member to array
}
// Find element at position
Count = 0;
@@ -526,7 +532,7 @@ const char * CDataMember::GetChStr( const char * Path, const char * Default, boo
return Member->Value;
}
else if (Member && Create && (Member->Type == jtNull)) {
Member->SetValue( jtString, Default );
Member->SetStr( Default );
return Member->Value;
}
else {
@@ -546,7 +552,7 @@ const char * CDataMember::GetChStr( const char * Path, int &Len, const char * De
return Member->Value;
}
else if (Member && Create && (Member->Type == jtNull)) {
Member->SetValue( jtString, Default );
Member->SetStr( Default );
Len = Member->Len;
return Member->Value;
}

View File

@@ -41,7 +41,7 @@ class CDataMember
CDataMember * CreateChild( const char * Name, const int Len = -1 );
// Set Member value
bool SetValue( EDataType Type, const char * Value = NULL, int Len = -1 );
bool SetValue( EDataType Type, const char * Value = NULL, int Len = -1 );
bool SetValuePtr( EDataType pType, const char * pValue, int pLen = -1 );
public:
@@ -67,11 +67,11 @@ public:
const int GetLen( const char * Path );
CDataMember * GetChild( const char * Path, bool Create = false );
CDataMember * GetChFirstChild( const char * Path );
CDataMember * GetChElement( const char * Path, const int Index );
CDataMember * GetChFirstChild( const char * Path, bool Create = false );
CDataMember * GetChElement( const char * Path, const int Index, bool Create = false );
inline CDataMember * GetFirstChild() { return FirstChild; };
inline CDataMember * GetElement( const int Index ) { return GetChElement( NULL, Index ); };
inline CDataMember * GetFirstChild() { return GetChFirstChild( NULL, false ); };
inline CDataMember * GetElement( const int Index ) { return GetChElement( NULL, Index, false ); };
inline CDataMember * GetParent() { return Parent; };
inline CDataMember * GetPrevPeer() { return PrevPeer; };
@@ -83,11 +83,11 @@ public:
const long GetChInt( const char * Path, long Default = 0, bool Create = false, const char * Mask = NULL );
const double GetChFloat( const char * Path, double Default = 0.0, bool Create = false, const char * Mask = NULL );
inline const char * GetStr( const char * Default = NULL, bool Create = false ) { return GetChStr( NULL, Default, Create ); };
inline const char * GetStr( int &Len, const char * Default = NULL, bool Create = false ) { return GetChStr( NULL, Len, Default, Create ); };
inline const bool GetBool( bool Default = false, bool Create = false ) { return GetChBool( NULL, Default, Create ); };
inline const long GetInt( long Default = 0, bool Create = false, const char * Mask = NULL ) { return GetChInt( NULL, Default, Create, Mask ); };
inline const double GetFloat( double Default = 0.0, bool Create = false, const char * Mask = NULL ) { return GetChFloat( NULL, Default, Create, Mask ); };
inline const char * GetStr( const char * Default = NULL ) { return GetChStr( NULL, Default, false ); };
inline const char * GetStr( int &Len, const char * Default = NULL ) { return GetChStr( NULL, Len, Default, false ); };
inline const bool GetBool( bool Default = false ) { return GetChBool( NULL, Default, false ); };
inline const long GetInt( long Default = 0, const char * Mask = NULL ) { return GetChInt( NULL, Default, false, Mask ); };
inline const double GetFloat( double Default = 0.0, const char * Mask = NULL ) { return GetChFloat( NULL, Default, false, Mask ); };
bool SetChBool( const char * Path, const bool Value );
bool SetChInt( const char * Path, const long Value, const char * Mask = NULL );

View File

@@ -22,8 +22,12 @@ extern char * ProcessName;
//---------------------------------------------------------------------------
CDeviceCore::CDeviceCore( const char * pName, const char * pType ) :
CFunctionCore( pName, pType )
//CFunctionCore * NewDeviceCore( const char * Name ) {
// return (CFunctionCore*) new CDeviceCore( Name );
//}
//---------------------------------------------------------------------------
CDeviceCore::CDeviceCore( const char * pName, const char * pType ) : CFunctionCore( pName, pType )
{
// Clear Parameters
FirstDevice = NULL;

View File

@@ -61,6 +61,12 @@ struct SDeviceParam {
//---------------------------------------------------------------------------
// Function Constructor List
#define TYPE_DEVICE "Device"
//CFunctionCore * NewDeviceCore( const char * Name );
//---------------------------------------------------------------------------
class CDeviceCore : public CFunctionCore
{
protected:
@@ -168,7 +174,7 @@ protected:
public:
// Life cycle
CDeviceCore( const char * pName, const char * Type = "Device" );
CDeviceCore( const char * pName, const char * pType = TYPE_DEVICE );
virtual ~CDeviceCore();
// Generate events

View File

@@ -22,8 +22,13 @@ extern char * ProcessName;
//---------------------------------------------------------------------------
CFileCore::CFileCore( const char * pName, const char * pType ) :
CFunctionCore( pName, pType )
// Function Constructor
CFunctionCore * NewFileCore( const char * Name ) {
return (CFunctionCore*) new CFileCore( Name );
}
//---------------------------------------------------------------------------
CFileCore::CFileCore( const char * pName, const char * pType ) : CFunctionCore( pName, pType )
{
FirstFile = NULL;
}

View File

@@ -35,6 +35,11 @@ struct SFileHandle
};
//---------------------------------------------------------------------------
// Function Constructor List
#define TYPE_FILE "File"
CFunctionCore * NewFileCore( const char * Name );
//---------------------------------------------------------------------------
class CFileCore : public CFunctionCore
{
private:
@@ -60,7 +65,7 @@ private:
public:
// Life cycle
CFileCore( const char * pName, const char * pType = "File" );
CFileCore( const char * pName, const char * pType = TYPE_FILE );
virtual ~CFileCore();
// Manage files

View File

@@ -20,8 +20,14 @@ extern CApplication * Application;
//---------------------------------------------------------------------------
// Function Constructor
//CFunctionCore * NewFunctionCore( const char * Name ) {
// return new CFunctionCore( Name, "Function" );
//}
//---------------------------------------------------------------------------
// Life cycle
CFunctionCore::CFunctionCore( const char * pName, const char * pType )
CFunctionCore::CFunctionCore( const char * pName, const char * pType ) : Type( pType )
{
// Set name
if (pName) {
@@ -32,25 +38,8 @@ CFunctionCore::CFunctionCore( const char * pName, const char * pType )
Name = NULL;
}
// Set Type
if (pType) {
Type = (char*)malloc( strlen(pType)+1 );
strcpy( Type, pType );
}
else {
Type = NULL;
}
// Channels
FirstChannel = NULL;
// List
Application->AddFunction( this );
// Data Tree
DataTree = Application->DataTree;
ConfigMember = NULL;
LinkConfigMember = NULL;
FirstChannel = NULL;
// Logging
Log = Application->Log;
@@ -107,20 +96,25 @@ CFunctionCore::~CFunctionCore()
// Destroy Name
if (Name) free( Name );
if (Type) free( Type );
}
//---------------------------------------------------------------------------
bool CFunctionCore::LoadConfigData()
bool CFunctionCore::Init( CDataMember * FunctionConfig )
{
CDataMember * TempMember;
// Load configuration
CDataMember * ItemConfig;
CDataMember * ChannelConfig;
EDebugLevel pLogLevel;
int pLogOutput;
char * TempStr;
// Validate
if (!FunctionConfig )
return false;
// Get debug level
pLogLevel = dlNone;
TempStr = (char*)ConfigMember->GetChStr( "Log/Level", "Medium", true );
TempStr = (char*)FunctionConfig->GetChStr( "Log/Level", "Medium", true );
if (TempStr)
{
if (!strcasecmp( TempStr, "Low" ))
@@ -133,66 +127,63 @@ bool CFunctionCore::LoadConfigData()
// Set debug output
pLogOutput = 0;
if ((TempMember = ConfigMember->GetChild( "Log/Output", true )))
ItemConfig = FunctionConfig->GetChild( "Log/Output[0]", true ); // Create first element if not exist
while (ItemConfig)
{
TempMember = TempMember->GetFirstChild();
while (TempMember)
if ((TempStr = (char*)ItemConfig->GetStr( "Normal" ))) // Set default value "Normal" if not set
{
if ((TempStr = (char*)TempMember->GetStr()))
{
if (!strcasecmp( TempStr, "Normal"))
pLogOutput |= OUT_NORMAL;
else if (!strcasecmp( TempStr, "Bin"))
pLogOutput |= OUT_BIN;
else if (!strcasecmp( TempStr, "Hex"))
pLogOutput |= OUT_HEX;
else if (!strcasecmp( TempStr, "Count"))
pLogOutput |= OUT_COUNT;
else if (!strcasecmp( TempStr, "AsIs"))
pLogOutput |= OUT_ASIS;
else if (!strcasecmp( TempStr, "CRLF"))
pLogOutput |= OUT_CRLF;
}
// Next
TempMember = TempMember->GetNextPeer();
if (!strcasecmp( TempStr, "Normal")) // Normal ASCII -> Unless "AsIs", print special chars as "."
pLogOutput |= OUT_NORMAL;
else if (!strcasecmp( TempStr, "Bin")) // Print as Binary value ('1' and '0')
pLogOutput |= OUT_BIN;
else if (!strcasecmp( TempStr, "Hex")) // Print as Hexadecimal value (0-9,A-F)
pLogOutput |= OUT_HEX;
else if (!strcasecmp( TempStr, "Count")) // Print number of characters
pLogOutput |= OUT_COUNT;
else if (!strcasecmp( TempStr, "AsIs")) // Use with "Normal" -> Do not print special chars as "."
pLogOutput |= OUT_ASIS;
else if (!strcasecmp( TempStr, "CRLF")) // Add \r\n at end of line if not present
pLogOutput |= OUT_CRLF;
else
pLogOutput |= OUT_NORMAL;
}
ItemConfig = ItemConfig->GetNextPeer();
}
// Set Logging
SetLogParam( pLogLevel, pLogOutput );
// Load Channels
TempMember = ConfigMember->GetChFirstChild( "Channels" );
while (TempMember)
ChannelConfig = FunctionConfig->GetChFirstChild( "Channels", true );
while (ChannelConfig)
{
if (TempMember->GetName()) {
AddChannel( TempMember->GetName(),
TempMember->GetChBool( "InputEnabled", true, true ),
TempMember->GetChBool( "OutputEnabled", false, true ));
if (ChannelConfig->GetName()) {
AddChannel( ChannelConfig->GetName(),
ChannelConfig->GetChBool( "InputEnabled", true, true ),
ChannelConfig->GetChBool( "OutputEnabled", false, true ));
}
// Next
TempMember = TempMember->GetNextPeer();
ChannelConfig = ChannelConfig->GetNextPeer();
}
return true;
}
//---------------------------------------------------------------------------
bool CFunctionCore::LoadChannelLinkData()
bool CFunctionCore::InitChannelLinks( CDataMember * LinkConfig )
{
TChannel * Channel;
CDataMember * ChannelMember;
CDataMember * FunctionMember;
// Validate
if (!LinkConfig)
return false;
// Process each Channel
ChannelMember = LinkConfigMember->GetFirstChild();
ChannelMember = LinkConfig->GetFirstChild();
while (ChannelMember)
{
if ((Channel = GetChannel( ChannelMember->GetName() )))
{
FunctionMember = ChannelMember->GetFirstChild();
FunctionMember = ChannelMember->GetElement( 0 );
while (FunctionMember)
{
// Get Parameters
@@ -200,11 +191,9 @@ bool CFunctionCore::LoadChannelLinkData()
FunctionMember->GetChStr( "Function" ),
FunctionMember->GetChStr( "Channel" ),
FunctionMember->GetChBool( "Bidirectional" ) );
// Next
FunctionMember = FunctionMember->GetNextPeer();
}
}
// Next
ChannelMember = ChannelMember->GetNextPeer();
}
@@ -212,69 +201,6 @@ bool CFunctionCore::LoadChannelLinkData()
}
//---------------------------------------------------------------------------
bool CFunctionCore::Init()
{
// Report status
if (Log) Log->Message( LogLevel, dlLow, "%s: Function '%s' - Initialised", ProcessName, Name );
return true;
}
//---------------------------------------------------------------------------
bool CFunctionCore::InitConfig( const char * pConfigPath )
{
// Validate
if (!DataTree || !(ConfigMember = DataTree->GetChild( pConfigPath, true )))
return false;
// Load configuration
LoadConfigData();
Init();
return true;
}
//---------------------------------------------------------------------------
bool CFunctionCore::InitConfig( CDataMember * pBaseMember )
{
// Validate
if (!DataTree || !(ConfigMember = pBaseMember ))
return false;
// Load configuration
LoadConfigData();
Init();
return true;
}
//---------------------------------------------------------------------------
bool CFunctionCore::InitChannelLinks( const char * pLinkConfigPath )
{
// Validate
if (!DataTree || !(LinkConfigMember = DataTree->GetChild( pLinkConfigPath, true )))
return false;
// Load configuration
LoadChannelLinkData();
return true;
}
//---------------------------------------------------------------------------
bool CFunctionCore::InitChannelLinks( CDataMember *pLinkConfigMember )
{
// Validate
if (!DataTree || !(LinkConfigMember = pLinkConfigMember))
return false;
// Load configuration
LoadChannelLinkData();
return true;
}
//---------------------------------------------------------------------------
bool CFunctionCore::SetLogParam( EDebugLevel pDebugLevel, int pOutputDisplay )
{
// Output

View File

@@ -48,20 +48,21 @@ struct SChannelLink
};
//---------------------------------------------------------------------------
// Function Constructor
#define TYPE_FUNCTION "Function"
//CFunctionCore * NewFunctionCore( const char * Name );
//---------------------------------------------------------------------------
class CFunctionCore
{
protected:
// Function Definition
char * Name;
char * Type;
// Configuration
CDataMember * DataTree;
CDataMember * ConfigMember;
CDataMember * LinkConfigMember;
const char * Type;
char * Name;
// Channels
TChannel * FirstChannel;
TChannel * FirstChannel;
// Logging
CLogCore * Log;
@@ -73,35 +74,26 @@ protected:
int StoredOutputLen;
// Manage Channel
inline TChannel * GetChannel( const char * Name ) {
if (!Name) return NULL;
inline TChannel * GetChannel( const char * pName ) {
if (!pName) return NULL;
TChannel * Channel = FirstChannel;
while (Channel && strcmp( Name, Channel->Name ))
while (Channel && strcmp( pName, 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 );
public:
// Life cycle
CFunctionCore( const char * pName, const char * Type );
CFunctionCore( const char * pName, const char * pType = TYPE_FUNCTION );
virtual ~CFunctionCore();
// Load Configuration
virtual bool Init();
bool InitConfig( const char * pConfigPath );
bool InitConfig( CDataMember * pConfigMember );
bool InitChannelLinks( const char * pLinkConfigPath );
bool InitChannelLinks( CDataMember *pLinkConfigMember );
virtual bool Init( CDataMember * FunctionConfig );
virtual bool InitChannelLinks( CDataMember *LinkConfig );
// Set Parameters Manually
bool SetLogParam( EDebugLevel pDebugLevel, int pOutputDisplay );

View File

@@ -819,6 +819,13 @@ bool CJSONparse::PrintObject( CDataMember * Object, const int Indent )
if (write( OutputHandle, "{", 1 ) < 0)
return false;
// Check if empty
if (Object->Len == 0) {
if (write( OutputHandle, "}", 1 ) < 0)
return false;
return true;
}
// Extend spacer
if (Indent) {
memset( &Spacer[SpacerLen], ' ', 2 );
@@ -930,6 +937,13 @@ bool CJSONparse::PrintArray( CDataMember * Array, const int Indent )
if (write( OutputHandle, "[", 1 ) < 0)
return false;
// Check if empty
if (Array->Len == 0) {
if (write( OutputHandle, "]", 1 ) < 0)
return false;
return true;
}
// Extend spacer
if (Indent) {
memset( &Spacer[SpacerLen], ' ', 2 );

View File

@@ -34,8 +34,13 @@ extern CApplication * Application;
//---------------------------------------------------------------------------
CSelectableCore::CSelectableCore( const char * pName, const char * pType ) :
CFunctionCore( pName, pType )
// Function Constructor
CFunctionCore * NewSelectableCore( const char * Name ) {
return (CFunctionCore*) new CSelectableCore( Name );
}
//---------------------------------------------------------------------------
CSelectableCore::CSelectableCore( const char * pName, const char * pType ) : CFunctionCore( pName, pType )
{
// Quick access
Selector = Application->Selector;
@@ -64,53 +69,47 @@ CSelectableCore::~CSelectableCore()
}
//---------------------------------------------------------------------------
bool CSelectableCore::LoadConfigData()
bool CSelectableCore::Init( CDataMember * FunctionConfig )
{
CDataMember * TempMember;
CDataMember * HandleConfig;
CDataMember * AddressDef;
CDataMember * SerialConfig;
THandle * Handle;
char * Type;
char * Name;
char Path[100];
char * Address;
char * Port;
char * ParityText;
char * FlowCtrlText;
short Parity;
short FlowCtrl;
short Queue;
long Delay;
// Call Previous load config
CFunctionCore::LoadConfigData();
if (!CFunctionCore::Init( FunctionConfig ))
return false;
// Load Handles
if ((TempMember = ConfigMember->GetChild( "Handles", false ))) {
TempMember = TempMember->GetFirstChild();
}
while (TempMember)
HandleConfig = FunctionConfig->GetChFirstChild( "Handles", true );
while (HandleConfig)
{
// Check if name is valid
if (!TempMember->GetName() || !*TempMember->GetName())
continue;
// Create Handle and channel link
Handle = CreateHandle( TempMember->GetName(), false );
Handle->Channel = GetChannel( TempMember->GetChStr( "Channel" ) );
Handle = CreateHandle( HandleConfig->GetName(), false );
Handle->Channel = GetChannel( HandleConfig->GetChStr( "Channel" ) );
Type = (char*)TempMember->GetChStr( "Type", "TCPclient", true );
Type = (char*)HandleConfig->GetChStr( "Type", "TCPclient", true );
if (!strcasecmp( Type, "Serial" ))
{
if ((Name = (char*)TempMember->GetChStr( "Port/Name", NULL ))) {
sprintf( Path, "Address/%s/Address", Name );
Address = (char*)DataTree->GetChStr( Path, NULL, true ); // Get address list value
}
else {
Address = (char*)TempMember->GetChStr( "Port/Address", NULL, true ); // Get default value
if ((Name = (char*)HandleConfig->GetChStr( "Port/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) {
Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value
} else {
Address = (char*)HandleConfig->GetChStr( "Port/Address", NULL, true ); // Get default value
}
SetSerialHandle( Handle, Address );
// Update configuration if specified
if ((SerialConfig = TempMember->GetChild( "Port/SerialConfig", false )))
if ((SerialConfig = HandleConfig->GetChild( "Port/SerialConfig", false )))
{
ParityText = (char*)SerialConfig->GetChStr( "Parity", "none", true );
if (!strcasecmp( ParityText, "none" ))
@@ -143,117 +142,101 @@ bool CSelectableCore::LoadConfigData()
}
else if (!strcasecmp( Type, "LinePrinter" ))
{
if ((Name = (char*)TempMember->GetChStr( "Port/Name", NULL ))) {
sprintf( Path, "Address/%s/Address", Name );
Address = (char*)DataTree->GetChStr( Path, NULL, true ); // Get address list value
}
else {
Address = (char*)TempMember->GetChStr( "Port/Address", NULL, true ); // Get default value
if ((Name = (char*)HandleConfig->GetChStr( "Port/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) {
Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value
} else {
Address = (char*)HandleConfig->GetChStr( "Port/Address", NULL, true ); // Get default value
}
SetLinePrinterHandle( Handle, Address );
}
else if (!strcasecmp( Type, "UNIXserver" ))
{
if ((Name = (char*)TempMember->GetChStr( "Socket/Name", NULL ))) {
sprintf( Path, "Address/%s/Address", Name );
Address = (char*)DataTree->GetChStr( Path, NULL, true ); // Get AddressList Address value
if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) {
Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value
} else {
Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
}
else {
Address = (char*)TempMember->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
}
SetUnixHandle( Handle, ctUNIXserver, Address );
Queue = HandleConfig->GetChInt( "Socket/Queue", 2, true );
SetUnixHandle( Handle, ctUNIXserver, Address, Queue );
}
else if (!strcasecmp( Type, "UNIXclient" ))
{
if ((Name = (char*)TempMember->GetChStr( "Socket/Name", NULL ))) {
sprintf( Path, "Address/%s/Address", Name );
Address = (char*)DataTree->GetChStr( Path, NULL, true ); // Get AddressList Address value
if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) {
Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value
} else {
Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
}
else {
Address = (char*)TempMember->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
}
SetUnixHandle( Handle, ctUNIXclient, Address );
SetUnixHandle( Handle, ctUNIXclient, Address, 0 );
}
else if (!strcasecmp( Type, "UDPserver" ))
{
if ((Name = (char*)TempMember->GetChStr( "Socket/Name", NULL ))) {
sprintf( Path, "Address/%s/Address", Name );
Address = (char*)DataTree->GetChStr( Path, NULL, true ); // Get AddressList Address value
sprintf( Path, "Address/%s/Port", Name );
Port = (char*)DataTree->GetChStr( Path, "0", true ); // Get AddressList Port value
if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) {
Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value
Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value
} else {
Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
Port = (char*)HandleConfig->GetChStr( "Socket/Port", "0", true ); // Get default Port value
}
else {
Address = (char*)TempMember->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
Port = (char*)TempMember->GetChStr( "Socket/Port", "0", true ); // Get default Port value
}
Delay = TempMember->GetChInt( "Socket/ResolveDelay", 0, true );
SetSocketHandle( Handle, ctUDPserver, Address, strlcase(Port), Delay );
Delay = HandleConfig->GetChInt( "Socket/ResolveDelay", 0, true );
SetSocketHandle( Handle, ctUDPserver, Address, strlcase(Port), 0, Delay );
}
else if (!strcasecmp( Type, "UDPclient" ))
{
if ((Name = (char*)TempMember->GetChStr( "Socket/Name", NULL ))) {
sprintf( Path, "Address/%s/Address", Name );
Address = (char*)DataTree->GetChStr( Path, NULL, true ); // Get AddressList Address value
sprintf( Path, "Address/%s/Port", Name );
Port = (char*)DataTree->GetChStr( Path, "0", true ); // Get AddressList Port value
if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) {
Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value
Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value
} else {
Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
Port = (char*)HandleConfig->GetChStr( "Socket/Port", "0", true ); // Get default Port value
}
else {
Address = (char*)TempMember->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
Port = (char*)TempMember->GetChStr( "Socket/Port", "0", true ); // Get default Port value
}
Delay = TempMember->GetChInt( "Socket/ResolveDelay", 0, true );
SetSocketHandle( Handle, ctUDPclient, Address, strlcase(Port), Delay );
Delay = HandleConfig->GetChInt( "Socket/ResolveDelay", 0, true );
SetSocketHandle( Handle, ctUDPclient, Address, strlcase(Port), 0, Delay );
}
else if (!strcasecmp( Type, "TCPserver" ))
{
if ((Name = (char*)TempMember->GetChStr( "Socket/Name", NULL ))) {
sprintf( Path, "Address/%s/Address", Name );
Address = (char*)DataTree->GetChStr( Path, NULL, true ); // Get AddressList Address value
sprintf( Path, "Address/%s/Port", Name );
Port = (char*)DataTree->GetChStr( Path, "0", true ); // Get AddressList Port value
if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) {
Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value
Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value
} else {
Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
Port = (char*)HandleConfig->GetChStr( "Socket/Port", "0", true ); // Get default Port value
}
else {
Address = (char*)TempMember->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
Port = (char*)TempMember->GetChStr( "Socket/Port", "0", true ); // Get default Port value
}
Delay = TempMember->GetChInt( "Socket/ResolveDelay", 0, true );
SetSocketHandle( Handle, ctTCPserver, Address, strlcase(Port), Delay );
Delay = HandleConfig->GetChInt( "Socket/ResolveDelay", 0, true );
Queue = HandleConfig->GetChInt( "Socket/Queue", 2, true );
SetSocketHandle( Handle, ctTCPserver, Address, strlcase(Port), Queue, Delay );
}
else if (!strcasecmp( Type, "TCPclient" ))
{
if ((Name = (char*)TempMember->GetChStr( "Socket/Name", NULL ))) {
sprintf( Path, "Address/%s/Address", Name );
Address = (char*)DataTree->GetChStr( Path, NULL, true ); // Get AddressList Address value
sprintf( Path, "Address/%s/Port", Name );
Port = (char*)DataTree->GetChStr( Path, "0", true ); // Get AddressList Port value
if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) {
Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value
Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value
} else {
Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
Port = (char*)HandleConfig->GetChStr( "Socket/Port", "0", true ); // Get default Port value
}
else {
Address = (char*)TempMember->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
Port = (char*)TempMember->GetChStr( "Socket/Port", "0", true ); // Get default Port value
}
Delay = TempMember->GetChInt( "Socket/ResolveDelay", 0, true );
SetSocketHandle( Handle, ctTCPclient, Address, strlcase(Port), Delay );
Delay = HandleConfig->GetChInt( "Socket/ResolveDelay", 0, true );
SetSocketHandle( Handle, ctTCPclient, Address, strlcase(Port), 0, Delay );
}
else if (!strcasecmp( Type, "ForkPipe" )) {
Address = (char*)TempMember->GetChStr( "Fork/ExecPath", NULL, true ); // Get default value
Address = (char*)HandleConfig->GetChStr( "Fork/ExecPath", NULL, true ); // Get default value
SetForkPipeHandle( Handle, Address );
}
// Set Auto Mange
SetAutoManage( Handle, TempMember->GetChBool( "AutoManage/Enabled", true, true ),
TempMember->GetChBool( "AutoManage/Persistent", false, true ),
TempMember->GetChInt( "AutoManage/ReopenDelay", 2000, true ),
TempMember->GetChInt( "AutoManage/CloseTimeout", 2000, true ));
// Set Auto Manage
SetAutoManage( Handle, HandleConfig->GetChBool( "AutoManage/Enabled", true, true ),
HandleConfig->GetChBool( "AutoManage/Persistent", false, true ),
HandleConfig->GetChInt( "AutoManage/ReopenDelay", 2000, true ),
HandleConfig->GetChInt( "AutoManage/CloseTimeout", 2000, true ));
// Input buffer
SetInBuffer( Handle, TempMember->GetChInt( "InputBuffer/Size", 0 ),
TempMember->GetChInt( "InputBuffer/Timeout", 250 ),
TempMember->GetChStr( "InputBuffer/Marker", "" ),
TempMember->GetChInt( "InputBuffer/MarkerLen", 0 ) );
SetOutBuffer( Handle, TempMember->GetChInt( "OutputBuffer/Size", 0 ) );
SetInBuffer( Handle, HandleConfig->GetChInt( "InputBuffer/Size", 0 ),
HandleConfig->GetChInt( "InputBuffer/Timeout", 250 ),
HandleConfig->GetChStr( "InputBuffer/Marker", "" ),
HandleConfig->GetChInt( "InputBuffer/MarkerLen", 0 ) );
SetOutBuffer( Handle, HandleConfig->GetChInt( "OutputBuffer/Size", 0 ) );
// Next
TempMember = TempMember->GetNextPeer();
HandleConfig = HandleConfig->GetNextPeer();
}
return true;
@@ -458,7 +441,7 @@ bool CSelectableCore::SetForkPipeHandle( THandle * Handle, const char * ExecPath
}
//---------------------------------------------------------------------------
bool CSelectableCore::SetUnixHandle( THandle * Handle, EConnectType Type, const char * FileName )
bool CSelectableCore::SetUnixHandle( THandle * Handle, EConnectType Type, const char * FileName, short Queue )
{
// Validate
if (!Handle || !FileName ||
@@ -478,6 +461,7 @@ bool CSelectableCore::SetUnixHandle( THandle * Handle, EConnectType Type, const
// Set name
Handle->Path = (char*)malloc( strlen(FileName)+1 );
strcpy( Handle->Path, FileName );
Handle->Queue = Queue;
// Log event
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Set as %s [%s]",
@@ -486,7 +470,7 @@ bool CSelectableCore::SetUnixHandle( THandle * Handle, EConnectType Type, const
}
//---------------------------------------------------------------------------
bool CSelectableCore::SetSocketHandle( THandle * Handle, EConnectType Type, const char * HostName, const char * PortName, long ResolveDelay )
bool CSelectableCore::SetSocketHandle( THandle * Handle, EConnectType Type, const char * HostName, const char * PortName, short Queue, long ResolveDelay )
{
// Validate
if (!Handle || !HostName || !PortName ||
@@ -517,6 +501,8 @@ bool CSelectableCore::SetSocketHandle( THandle * Handle, EConnectType Type, con
Handle->AddressList = NULL;
Handle->AddressInfo = NULL;
Handle->Queue = Queue;
// Log event
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Set as %s [%s:%s]",
ProcessName, Name, Handle->Name, ConnectTypeName[Type], HostName, PortName );
@@ -897,7 +883,7 @@ THandle * CSelectableCore::OpenUNIXserverSocket( THandle * Handle )
};
// Create que for 5 connections
if (listen( Handle->FD, 5 ) < 0)
if (listen( Handle->FD, Handle->Queue ) < 0)
{
// Log Event
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Failed to listen on UNIX Server socket [%s] (%s)",
@@ -1060,7 +1046,7 @@ THandle * CSelectableCore::OpenUNIXremoteSocket( THandle * Handle )
// Create Remote Client Handle
sprintf( ClientName, "%s-%d", Handle->Name, ClientFD );
*RemoteClient = CreateHandle( ClientName, false );
if (!SetUnixHandle( *RemoteClient, ctUNIXremote, Handle->Path )) {
if (!SetUnixHandle( *RemoteClient, ctUNIXremote, Handle->Path, 0 )) {
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - UNIX Server failed to configure Remote Client connection (%s)",
ProcessName, Name, Handle->Name, strerror(errno) );
return NULL;
@@ -1286,7 +1272,7 @@ THandle * CSelectableCore::OpenUDPremoteSocket( THandle * Handle, char * ClientA
// Create Remote Client Handle
sprintf( ClientName, "%s-%d", Handle->Name, ClientCount );
*RemoteClient = CreateHandle( ClientName, false );
if (!SetSocketHandle( *RemoteClient, ctUDPremote, ClientAddress, ClientPort, 0 )) {
if (!SetSocketHandle( *RemoteClient, ctUDPremote, ClientAddress, ClientPort, 0, 0 )) {
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - UDP Server failed to configure Remote Client connection (%s)",
ProcessName, Name, Handle->Name, strerror(errno) );
return NULL;
@@ -1442,7 +1428,7 @@ THandle * CSelectableCore::OpenTCPserverSocket( THandle * Handle, bool DelayReso
};
// Create que for 5 connections
if (listen( Handle->FD, 5 ) < 0)
if (listen( Handle->FD, Handle->Queue ) < 0)
{
// Log Event
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Failed to listen on TCP Server socket [%s:%s] (%s)",
@@ -1524,7 +1510,7 @@ THandle * CSelectableCore::OpenTCPremoteSocket( THandle * Handle )
// Create Remote Client Handle
sprintf( ClientName, "%s-%d", Handle->Name, ClientFD );
*RemoteClient = CreateHandle( ClientName, false );
if (!SetSocketHandle( *RemoteClient, ctTCPremote, ClientAddress, ClientPort, 0 )) {
if (!SetSocketHandle( *RemoteClient, ctTCPremote, ClientAddress, ClientPort, 0, 0 )) {
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - TCP Server failed to configure Remote Client connection (%s)",
ProcessName, Name, Handle->Name, strerror(errno) );
return NULL;

View File

@@ -100,6 +100,7 @@ struct SHandle {
struct addrinfo * AddressList; // List of resolved IP Addresses for host name
struct addrinfo * AddressInfo; // Current selected IP Address
bool AddressFailed; // Indicate failure to connect to address
short Queue; // Max waiting connections
long ResolveDelay; // Delay before resolving hostname via DNS
// Serial Port config
@@ -173,6 +174,12 @@ public:
//---------------------------------------------------------------------------
// Function Constructor
#define TYPE_SELECTABLE "Selectable"
CFunctionCore * NewSelectableCore( const char * Name );
//---------------------------------------------------------------------------
class CSelectableCore : public CFunctionCore
{
protected:
@@ -182,9 +189,6 @@ protected:
// Select interface
CSelect * Selector;
// Configuration
virtual bool LoadConfigData();
// Managing File Handles
bool RemoveHandle( THandle * Handle );
bool DestroyHandle( THandle * Handle );
@@ -248,9 +252,12 @@ protected:
public:
// Life Cycle
CSelectableCore( const char * Name, const char * pType = "Selectable" );
CSelectableCore( const char * Name, const char * Type = TYPE_SELECTABLE );
virtual ~CSelectableCore();
// Configuration
virtual bool Init( CDataMember * FunctionConfig );
// Finding Handles
inline THandle * GetHandle( const char * HandleName )
{
@@ -281,8 +288,8 @@ public:
bool SetSerialHandleConfig( THandle * Handle, int Baudrate, short DataBits, short Parity, short StopBits, short FlowCtrl, int DataWait );
bool SetLinePrinterHandle( THandle * Handle, const char * FileName );
bool SetForkPipeHandle( THandle * Handle, const char * ExecPath );
bool SetUnixHandle( THandle * Handle, EConnectType Type, const char * FileName );
bool SetSocketHandle( THandle * Handle, EConnectType Type, const char * HostName, const char * PortName, long ResolveDelay );
bool SetUnixHandle( THandle * Handle, EConnectType Type, const char * FileName, short Queue );
bool SetSocketHandle( THandle * Handle, EConnectType Type, const char * HostName, const char * PortName, short Queue, long ResolveDelay );
bool ClearHandle( THandle * Handle );
// FD Operations

View File

@@ -20,8 +20,13 @@ extern char * ProcessName;
//---------------------------------------------------------------------------
CWatchdogCore::CWatchdogCore( const char * pName ) :
CSelectableCore( pName, "WatchdogClient" )
// Function Constructor
CFunctionCore * NewWatchdogCore( const char * Name ) {
return (CFunctionCore*) new CWatchdogCore( Name );
}
//---------------------------------------------------------------------------
CWatchdogCore::CWatchdogCore( const char * pName, const char * pType ) : CSelectableCore( pName, pType )
{
// Create protocol
Protocol = new CLiteProtocol( 50, '\x02', '\x03', '\x00' );
@@ -44,18 +49,6 @@ CWatchdogCore::~CWatchdogCore()
}
//---------------------------------------------------------------------------
bool CWatchdogCore::LoadConfigData()
{
// Call Previous load config
CSelectableCore::LoadConfigData();
// Set specific parameters
SetInterval( ConfigMember->GetChInt( "Parameters/PingInterval", 500, true ));
return true;
}
//---------------------------------------------------------------------------
bool CWatchdogCore::SetInterval( int pPingInterval )
{
PingInterval = pPingInterval;
@@ -63,14 +56,20 @@ bool CWatchdogCore::SetInterval( int pPingInterval )
}
//---------------------------------------------------------------------------
bool CWatchdogCore::Init()
bool CWatchdogCore::Init( CDataMember * FunctionConfig )
{
// Call Previous ingi
if (!CSelectableCore::Init( FunctionConfig ))
return false;
// Set specific parameters
SetInterval( FunctionConfig->GetChInt( "Parameters/PingInterval", 500, true ));
// Create handle and set reference, if not done
if (!(Ping = GetHandle( "Ping" )))
Ping = CreateHandle( "Ping", false );
// Previous init
return CSelectableCore::Init();
return true;
}
//---------------------------------------------------------------------------

View File

@@ -17,6 +17,12 @@
//---------------------------------------------------------------------------
// Function Constructor
#define TYPE_WATCHDOG "Watchdog"
CFunctionCore * NewWatchdogCore( const char * Name );
//---------------------------------------------------------------------------
class CWatchdogCore : public CSelectableCore
{
private:
@@ -32,17 +38,14 @@ private:
public:
// Life Cycle
CWatchdogCore( const char * pName );
CWatchdogCore( const char * pName, const char * pType = TYPE_WATCHDOG );
virtual ~CWatchdogCore();
// Load Configuration
virtual bool LoadConfigData();
// Manually set Configuration
bool SetInterval( int pPingInterval );
// Initialisation
virtual bool Init();
virtual bool Init( CDataMember * FunctionConfig );
// Process
virtual bool Process();