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:
Charl Wentzel
2017-07-16 20:29:01 +02:00
parent 8933ec1ae6
commit 434377f122
17 changed files with 809 additions and 205 deletions

View File

@@ -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;