Major Update:
- Implement new ApplicationCore:
- Manage Tools: Log, DataTree, JSONparser & Selector
- Load configuration, Manage FunctionBlocks
- FunctionCore & dirived classes, SignalCore:
- affects: SelectableCore, DeviceCore, FileCore, WatchdogCore
- Do not pass Log()
- Define and pass Type
- Update/reduce included headers
- Use ProcessName and Application global vars
- Get Log, DataTree from Application
- Use virtual Init() function to set must have Channels/Handles
- DataTreeCore:
- Bug fix: Check if child members exist and destroy in SetValuePtr()
- Add method GetFirstChild with BaseMember & Path
- Bug fix: do not use RootMember if no Parent in GetChildxxx() methods
- SignalCore, SelectCore:
- Use Application->Log()
- FunctionCore:
- Add itself to Application (function list)
- Add parameter: LinkConfigMember, Type
- Use virtual LoadConfigData() to configure from DataTree
- Rename methods: LoadConfig() -> InitConfig(),
InitLogging() -> SetLogParam(), SetDebugLevel() -> SetLogLevel()
- Add method: GetType(), LoadChannelLinkData(), InitChannelLinks()
- Modify LinkIn/OutputChannel() to use name for InFunction, not pointer
- SelectableCore & Dirived classes:
- Affects DeviceCore & WatchdogClient
- Rename parameter: Select -> Selector, BaseMember -> ConfigMember
- Get Selector from Application->Selector
- Change Handles JSON structure from Array to Key:Value pairs
- Bug fix: check if Selector exist during Input()
- Bug fix: do not set PortNo if not exist
This commit is contained in:
236
FunctionCore.cpp
236
FunctionCore.cpp
@@ -6,9 +6,8 @@
|
||||
*/
|
||||
|
||||
// redA Libraries
|
||||
#include "ApplicationCore.h"
|
||||
#include "FunctionCore.h"
|
||||
#include "TimingCore.h"
|
||||
#include "LogCore.h"
|
||||
|
||||
// Standard C/C++ Libraries
|
||||
#include <stdio.h>
|
||||
@@ -17,12 +16,14 @@
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
extern char * ProcessName;
|
||||
// Global Vars
|
||||
extern char * ProcessName;
|
||||
extern CApplication * Application;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Life cycle
|
||||
CFunctionCore::CFunctionCore( const char * pName, CLogCore * pLog )
|
||||
CFunctionCore::CFunctionCore( const char * pName, const char * pType )
|
||||
{
|
||||
// Set name
|
||||
if (pName) {
|
||||
@@ -33,17 +34,30 @@ CFunctionCore::CFunctionCore( const char * pName, CLogCore * pLog )
|
||||
Name = NULL;
|
||||
}
|
||||
|
||||
// Data Tree
|
||||
DataTree = NULL;
|
||||
BaseMember = 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;
|
||||
|
||||
// Output
|
||||
Log = pLog;
|
||||
LogLevel = dlNone;
|
||||
LogOutput = OUT_NORMAL;
|
||||
Log = Application->Log;
|
||||
LogLevel = dlNone;
|
||||
LogOutput = OUT_NORMAL;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -90,75 +104,50 @@ CFunctionCore::~CFunctionCore()
|
||||
if (Log) Log->Message( LogLevel, dlLow, "%s: Function '%s' - Destroyed", ProcessName, Name );
|
||||
|
||||
// Destroy Name
|
||||
if (Name) {
|
||||
free( Name );
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CFunctionCore::LoadConfig( CDataTree * pDataTree, const char * pBasePath )
|
||||
{
|
||||
// Validate
|
||||
if (!(DataTree = pDataTree) || !(BaseMember = DataTree->GetMember( NULL, pBasePath, true )))
|
||||
return false;
|
||||
|
||||
// Load configuration
|
||||
LoadConfigData();
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CFunctionCore::LoadConfig( CDataTree * pDataTree, TDataMember * pBaseMember )
|
||||
{
|
||||
// Validate
|
||||
if (!(DataTree = pDataTree) || !(BaseMember = pBaseMember ))
|
||||
return false;
|
||||
|
||||
// Load configuration
|
||||
LoadConfigData();
|
||||
|
||||
return true;
|
||||
if (Name) free( Name );
|
||||
if (Type) free( Type );
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CFunctionCore::LoadConfigData()
|
||||
{
|
||||
TDataMember * TempMember;
|
||||
EDebugLevel pLogLevel;
|
||||
int pLogOutput;
|
||||
char * TempStr;
|
||||
|
||||
// Get debug level
|
||||
LogLevel = dlNone;
|
||||
TempStr = (char*)DataTree->GetStr( BaseMember, "Log/Level", "Medium", true );
|
||||
pLogLevel = dlNone;
|
||||
TempStr = (char*)DataTree->GetStr( ConfigMember, "Log/Level", "Medium", true );
|
||||
if (TempStr)
|
||||
{
|
||||
if (!strcasecmp( TempStr, "Low" ))
|
||||
LogLevel = dlLow;
|
||||
pLogLevel = dlLow;
|
||||
else if (!strcasecmp( TempStr, "Medium" ))
|
||||
LogLevel = dlMedium;
|
||||
pLogLevel = dlMedium;
|
||||
else if (!strcasecmp( TempStr, "High" ))
|
||||
LogLevel = dlHigh;
|
||||
pLogLevel = dlHigh;
|
||||
}
|
||||
|
||||
// Set debug output
|
||||
LogOutput = 0;
|
||||
TempMember = DataTree->GetMember( BaseMember, "Log/Output[0]", true );
|
||||
pLogOutput = 0;
|
||||
TempMember = DataTree->GetFirstChild( ConfigMember, "Log/Output", true );
|
||||
while (TempMember)
|
||||
{
|
||||
if (TempMember->Value)
|
||||
{
|
||||
if (!strcasecmp( TempMember->Value, "Normal"))
|
||||
LogOutput |= OUT_NORMAL;
|
||||
pLogOutput |= OUT_NORMAL;
|
||||
else if (!strcasecmp( TempMember->Value, "Bin"))
|
||||
LogOutput |= OUT_BIN;
|
||||
pLogOutput |= OUT_BIN;
|
||||
else if (!strcasecmp( TempMember->Value, "Hex"))
|
||||
LogOutput |= OUT_HEX;
|
||||
pLogOutput |= OUT_HEX;
|
||||
else if (!strcasecmp( TempMember->Value, "Count"))
|
||||
LogOutput |= OUT_COUNT;
|
||||
pLogOutput |= OUT_COUNT;
|
||||
else if (!strcasecmp( TempMember->Value, "AsIs"))
|
||||
LogOutput |= OUT_ASIS;
|
||||
pLogOutput |= OUT_ASIS;
|
||||
else if (!strcasecmp( TempMember->Value, "CRLF"))
|
||||
LogOutput |= OUT_CRLF;
|
||||
pLogOutput |= OUT_CRLF;
|
||||
}
|
||||
|
||||
// Next
|
||||
@@ -166,15 +155,17 @@ bool CFunctionCore::LoadConfigData()
|
||||
}
|
||||
|
||||
// Set Logging
|
||||
InitLogging( LogLevel, LogOutput );
|
||||
SetLogParam( pLogLevel, pLogOutput );
|
||||
|
||||
// Set debug output
|
||||
TempMember = DataTree->GetFirstChild( DataTree->GetMember( BaseMember, "Channels" ) );
|
||||
// Load Channels
|
||||
TempMember = DataTree->GetFirstChild( ConfigMember, "Channels", true );
|
||||
while (TempMember)
|
||||
{
|
||||
AddChannel( DataTree->GetStr( TempMember, "Name" ),
|
||||
DataTree->GetBool( TempMember, "InputEnabled", true, true ),
|
||||
DataTree->GetBool( TempMember, "OutputEnabled", false, true ));
|
||||
if (TempMember->Name) {
|
||||
AddChannel( TempMember->Name,
|
||||
DataTree->GetBool( TempMember, "InputEnabled", true, true ),
|
||||
DataTree->GetBool( TempMember, "OutputEnabled", false, true ));
|
||||
}
|
||||
|
||||
// Next
|
||||
TempMember = DataTree->GetNextChild( TempMember );
|
||||
@@ -184,20 +175,112 @@ bool CFunctionCore::LoadConfigData()
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CFunctionCore::InitLogging( EDebugLevel pDebugLevel, int pOutputDisplay )
|
||||
bool CFunctionCore::LoadChannelLinkData()
|
||||
{
|
||||
// Output
|
||||
LogLevel = pDebugLevel;
|
||||
LogOutput = pOutputDisplay;
|
||||
TChannel * Channel;
|
||||
TDataMember * ChannelMember;
|
||||
TDataMember * FunctionMember;
|
||||
|
||||
// Report status
|
||||
if (Log) Log->Message( LogLevel, dlLow, "%s: Function '%s' - Created", ProcessName, Name );
|
||||
// Process each Channel
|
||||
ChannelMember = DataTree->GetFirstChild( LinkConfigMember );
|
||||
while (ChannelMember)
|
||||
{
|
||||
if ((Channel = GetChannel( ChannelMember->Name )))
|
||||
{
|
||||
FunctionMember = DataTree->GetFirstChild( ChannelMember );
|
||||
while (FunctionMember)
|
||||
{
|
||||
// Get Parameters
|
||||
LinkOutputChannel( Channel->Name,
|
||||
DataTree->GetStr( FunctionMember, "Function" ),
|
||||
DataTree->GetStr( FunctionMember, "Channel" ),
|
||||
DataTree->GetBool( FunctionMember, "Bidirectional" ) );
|
||||
// Next
|
||||
FunctionMember = DataTree->GetNextChild( FunctionMember );
|
||||
}
|
||||
}
|
||||
// Next
|
||||
ChannelMember = DataTree->GetNextChild( ChannelMember );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CFunctionCore::SetDebugLevel( EDebugLevel pDebugLevel )
|
||||
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->GetMember( NULL, pConfigPath, true )))
|
||||
return false;
|
||||
|
||||
// Load configuration
|
||||
LoadConfigData();
|
||||
Init();
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CFunctionCore::InitConfig( TDataMember * 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->GetMember( NULL, pLinkConfigPath, true )))
|
||||
return false;
|
||||
|
||||
// Load configuration
|
||||
LoadChannelLinkData();
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CFunctionCore::InitChannelLinks( TDataMember *pLinkConfigMember )
|
||||
{
|
||||
// Validate
|
||||
if (!DataTree || !(LinkConfigMember = pLinkConfigMember))
|
||||
return false;
|
||||
|
||||
// Load configuration
|
||||
LoadChannelLinkData();
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CFunctionCore::SetLogParam( EDebugLevel pDebugLevel, int pOutputDisplay )
|
||||
{
|
||||
// Output
|
||||
LogLevel = pDebugLevel;
|
||||
LogOutput = pOutputDisplay;
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CFunctionCore::SetLogLevel( EDebugLevel pDebugLevel )
|
||||
{
|
||||
LogLevel = pDebugLevel;
|
||||
return true;
|
||||
@@ -242,13 +325,14 @@ TChannel * CFunctionCore::AddChannel( const char * ChannelName, const bool pInpu
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Automated Data Input/Output
|
||||
bool CFunctionCore::LinkInputChannel( const char * ChannelName, CFunctionCore * OutFunction, const char * OutChannelName, bool Bidirectional )
|
||||
bool CFunctionCore::LinkInputChannel( const char * ChannelName, const char * OutFunctionName, const char * OutChannelName, bool Bidirectional )
|
||||
{
|
||||
CFunctionCore * OutFunction = NULL;
|
||||
TChannel * Channel = NULL;
|
||||
TChannelLink ** LinkedChannel = NULL;
|
||||
|
||||
// Get Channel
|
||||
if (!OutFunction || !OutFunction || !(Channel = GetChannel( ChannelName ))) {
|
||||
if (!(OutFunction = Application->GetFunction( OutFunctionName )) || !(Channel = GetChannel( ChannelName ))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -276,25 +360,29 @@ bool CFunctionCore::LinkInputChannel( const char * ChannelName, CFunctionCore *
|
||||
|
||||
// Link Return direction as well
|
||||
if (Bidirectional) {
|
||||
return OutFunction->LinkInputChannel( OutChannelName, this, ChannelName, false );
|
||||
return OutFunction->LinkInputChannel( OutChannelName, Name, ChannelName, false );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CFunctionCore::LinkOutputChannel( const char * ChannelName, CFunctionCore * InFunction, const char * InChannelName, bool Bidirectional )
|
||||
bool CFunctionCore::LinkOutputChannel( const char * ChannelName, const char * InFunctionName, const char * InChannelName, bool Bidirectional )
|
||||
{
|
||||
TChannel * Channel = NULL;
|
||||
TChannel * OutChannel = NULL;
|
||||
CFunctionCore * InFunction = NULL;
|
||||
TChannel * InChannel = NULL;
|
||||
TChannelLink ** LinkedChannel = NULL;
|
||||
|
||||
// Get Channel
|
||||
if (!InFunction || !InChannelName || !(Channel = GetChannel( ChannelName ))) {
|
||||
// Check if Channels & Function exist
|
||||
if (!(OutChannel = GetChannel( ChannelName )) ||
|
||||
!(InFunction = Application->GetFunction( InFunctionName )) ||
|
||||
!(InChannel = InFunction->GetChannel( InChannelName )) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if linked Channel exists
|
||||
LinkedChannel = &(Channel->FirstOutput);
|
||||
LinkedChannel = &(OutChannel->FirstOutput);
|
||||
while (*LinkedChannel && (((*LinkedChannel)->Function != InFunction) || strcmp( (*LinkedChannel)->Name, InChannelName ) )) {
|
||||
LinkedChannel = &((*LinkedChannel)->Next);
|
||||
}
|
||||
@@ -317,7 +405,7 @@ bool CFunctionCore::LinkOutputChannel( const char * ChannelName, CFunctionCore *
|
||||
|
||||
// Link return direction as well
|
||||
if (Bidirectional) {
|
||||
return InFunction->LinkOutputChannel( InChannelName, this, ChannelName, false );
|
||||
return InFunction->LinkOutputChannel( InChannelName, Name, ChannelName, false );
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user