Merge branch 'master' into HitNotBLE

# Conflicts:
#	SelectableCore.cpp
#	SelectableCore.h
This commit is contained in:
Charl Wentzel
2019-04-03 17:02:52 +02:00
13 changed files with 680 additions and 562 deletions

View File

@@ -17,6 +17,7 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Global Vars // Global Vars
extern bool Terminate;
extern char * ProcessName; extern char * ProcessName;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -104,8 +105,7 @@ void CApplication::GetProcessName( char ** ProcessName, char * pFilePath )
if (TempStr[0] == '/') TempStr++; if (TempStr[0] == '/') TempStr++;
// Copy Process Name // Copy Process Name
*ProcessName = (char*)malloc( strlen(TempStr)+1 ); *ProcessName = strdup( TempStr );
strcpy( *ProcessName, TempStr );
// Remove extension // Remove extension
TempStr = strrchr( *ProcessName, '.' ); TempStr = strrchr( *ProcessName, '.' );
@@ -163,7 +163,7 @@ bool CApplication::LoadConfig()
} }
// Load Address List // Load Address List
if (!(AddressFile = (char*)Config->GetChStr( "Application/AddressList" ))) { if (!(AddressFile = (char*)Config->GetChStr( "Application/Addresses/List" ))) {
if (Log) Log->Message( dlLow, dlLow, "%s: No Address List file specified", ProcessName ); if (Log) Log->Message( dlLow, dlLow, "%s: No Address List file specified", ProcessName );
} }
else if (!JSONparser->ReadFromFile( "AddressList", AddressFile )) { else if (!JSONparser->ReadFromFile( "AddressList", AddressFile )) {
@@ -235,7 +235,7 @@ bool CApplication::InitApplication()
bool CApplication::InitFunction( CFunctionCore * Function ) bool CApplication::InitFunction( CFunctionCore * Function )
{ {
char FunctionPath[100]; char FunctionPath[100];
CDataMember * FunctionConfig = NULL; CDataMember * FunctionConfig;
// Validate // Validate
if (!Function) if (!Function)
@@ -274,7 +274,7 @@ bool CApplication::InitFunctions()
return false; return false;
} }
// Process each Channel // Process each Function
FunctionConfig = FunctionList->GetFirstChild(); FunctionConfig = FunctionList->GetFirstChild();
while (FunctionConfig) while (FunctionConfig)
{ {
@@ -358,8 +358,7 @@ bool CApplication::AddFunctionType( const char * Type, FFuncConstructor Construc
// Add new Type // Add new Type
*FunctionType = (TFunctionType*)calloc( sizeof(TFunctionType), 1 ); *FunctionType = (TFunctionType*)calloc( sizeof(TFunctionType), 1 );
(*FunctionType)->Name = (char*)malloc( strlen(Type)+1 ); (*FunctionType)->Name = strdup( Type );
strcpy( (*FunctionType)->Name, Type );
(*FunctionType)->Constructor = Constructor; (*FunctionType)->Constructor = Constructor;
return true; return true;
@@ -407,7 +406,8 @@ CFunctionCore * CApplication::GetFunction( const char * Name )
bool CApplication::Run( bool TerminateOnError ) bool CApplication::Run( bool TerminateOnError )
{ {
bool AllGood = true; bool CleanTerminate = true;
bool ProcessTerminate = false;
TFunctionItem * FunctionItem; TFunctionItem * FunctionItem;
// Check for FD Events/States // Check for FD Events/States
@@ -418,15 +418,17 @@ bool CApplication::Run( bool TerminateOnError )
// Process Functions // Process Functions
for (FunctionItem = FirstFunction; FunctionItem; FunctionItem = FunctionItem->Next ) for (FunctionItem = FirstFunction; FunctionItem; FunctionItem = FunctionItem->Next )
{ {
if (!FunctionItem->Function->Process()) ProcessTerminate = !FunctionItem->Function->Process();
{ if (TerminateOnError) {
if (TerminateOnError) if (ProcessTerminate)
Terminate = true;
if (FunctionItem->Function->WaitToTerminate && !ProcessTerminate)
CleanTerminate = false;
}
}
if (Terminate && TerminateOnError && CleanTerminate)
return false; return false;
else { else
AllGood = false; return true;
}
}
}
return AllGood;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -30,6 +30,7 @@ extern CApplication * Application;
CDeviceCore::CDeviceCore( const char * pName, const char * pType ) : CFunctionCore( pName, pType ) CDeviceCore::CDeviceCore( const char * pName, const char * pType ) : CFunctionCore( pName, pType )
{ {
// Polling // Polling
PollCycle = 0;
PollStep = 0; PollStep = 0;
PollInterval = 250; PollInterval = 250;
SetStartTime( &PollWait ); SetStartTime( &PollWait );
@@ -44,7 +45,8 @@ CDeviceCore::CDeviceCore( const char * pName, const char * pType ) : CFunctionCo
// Data Structures // Data Structures
DeviceInit = true; DeviceInit = true;
ConfigTypes = new CDataMember(); ConfigTypes = new CDataMember();
JSONparse = new CJSONparse( ConfigTypes ); ValueTree = new CDataMember();
JSONparse = new CJSONparse();
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -59,11 +61,14 @@ CDeviceCore::~CDeviceCore()
delete JSONparse; delete JSONparse;
if (ConfigTypes) if (ConfigTypes)
delete ConfigTypes; delete ConfigTypes;
if (ValueTree)
delete ValueTree;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool CDeviceCore::Init( CDataMember * FunctionConfig ) bool CDeviceCore::Init( CDataMember * FunctionConfig )
{ {
char * PersistFile = NULL;
char * ConfigName = NULL; char * ConfigName = NULL;
CDataMember * PollConfig = NULL; CDataMember * PollConfig = NULL;
int IntVal1; int IntVal1;
@@ -102,9 +107,20 @@ bool CDeviceCore::Init( CDataMember * FunctionConfig )
Log->Message( LogLevel, dlMedium, "%s/%s: Set polling param - Int:%d, T/O:%d, Max:%d", Log->Message( LogLevel, dlMedium, "%s/%s: Set polling param - Int:%d, T/O:%d, Max:%d",
ProcessName, Name, PollInterval, ReplyTimeout, MaxRetries ); ProcessName, Name, PollInterval, ReplyTimeout, MaxRetries );
// Load Value Tree from persistence file
if ((PersistFile = (char*)Config->GetChStr( "PersistFile", NULL, true ))) {
JSONparse->SetBase( ValueTree );
JSONparse->ReadFromFile( NULL, PersistFile );
Log->Message( LogLevel, dlMedium, "%s/%s: Persistence File '%s' loaded",
ProcessName, Name, PersistFile );
}
// Update Devices -- may want to do it from derived class intead // Update Devices -- may want to do it from derived class intead
if (DeviceInit) { if (DeviceInit) {
CDeviceCore::InitDevices( FunctionConfig ); InitDevices( FunctionConfig );
//JSONparse->SetBase( ValueTree );
//JSONparse->WriteToScreen( NULL, 2 );
} }
return true; return true;
@@ -113,86 +129,119 @@ bool CDeviceCore::Init( CDataMember * FunctionConfig )
bool CDeviceCore::InitDevices( CDataMember * FunctionConfig ) bool CDeviceCore::InitDevices( CDataMember * FunctionConfig )
{ {
CDataMember * DeviceData = NULL; CDataMember * DeviceConfig = NULL;
TDevice * Device = NULL; TDevice * Device = NULL;
char * Definition = NULL;
char * DeviceName = NULL; char * DeviceName = NULL;
int DeviceID = 0; int DeviceID = 0;
char * DeviceAddr = NULL; char * DeviceAddr = NULL;
char * DeviceType = NULL; char * DeviceType = NULL;
char * DataPath = NULL;
// Load Device Types // Load Device Types
DeviceData = Config->GetChFirstChild( "DeviceTypes", true ); DeviceConfig = Config->GetChFirstChild( "DeviceTypes", true );
while (DeviceData) while (DeviceConfig)
{ {
DeviceType = (char*)DeviceData->GetName(); DeviceType = (char*)DeviceConfig->GetName();
Device = AddDeviceType( DeviceType ); if (!DeviceConfig->isObject()) {
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Invalid device type config for '%s'",
ProcessName, Name, DeviceType );
DeviceConfig = DeviceConfig->GetNextPeer();
continue;
}
DataPath = (char*)DeviceConfig->GetChStr( "DataPath", NULL );
Device = AddDeviceType( DeviceType, DataPath );
if (Device) { if (Device) {
if (DeviceData->isString()) { if ((Definition = (char*)DeviceConfig->GetChStr( "Definition", NULL, false ))) {
if (JSONparse->ReadFromFile( DeviceType, DeviceData->GetStr() )) { // Contains file reference JSONparse->SetBase( ConfigTypes );
InitDeviceParams( Device, ConfigTypes->GetChild( DeviceType ) ); if (JSONparse->ReadFromFile( DeviceType, Definition )) { // Contains file reference
InitParamGroups( Device, ConfigTypes->GetChild( DeviceType ) ); InitDeviceParams( Device, ConfigTypes->GetChild( DeviceType ), NULL );
JSONparse->WriteToFile( DeviceType, DeviceData->GetStr() );
JSONparse->SetBase( ConfigTypes );
JSONparse->WriteToFile( DeviceType, Definition );
} }
else { else {
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Fail to load device type '%s' from file: '%s'", if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Fail to load device type '%s' from file: '%s'",
ProcessName, Name, DeviceType, DeviceData->GetStr() ); ProcessName, Name, DeviceType, DeviceConfig->GetStr() );
} }
} }
else if (DeviceData->isObject()) {
InitDeviceParams( Device, DeviceData ); // Contains definition
InitParamGroups( Device, DeviceData );
}
else { else {
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Invalid device type config for '%s'", InitDeviceParams( Device, DeviceConfig, NULL ); // Contains definition
ProcessName, Name, DeviceType );
} }
} }
DeviceData = DeviceData->GetNextPeer(); DeviceConfig = DeviceConfig->GetNextPeer();
} }
// Load Actual Devices // Load Actual Devices
DeviceData = Config->GetChFirstChild( "Devices", true ); DeviceConfig = Config->GetChFirstChild( "Devices", true );
while (DeviceData) while (DeviceConfig)
{ {
DeviceName = (char*)DeviceData->GetName(); DeviceName = (char*)DeviceConfig->GetName();
DeviceID = DeviceData->GetChInt( "ID", 0 ); if (!DeviceConfig->isObject()) {
DeviceAddr = (char*)DeviceData->GetChStr( "Address", NULL ); if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Invalid device config for '%s'",
DeviceType = (char*)DeviceData->GetChStr( "Type", NULL ); ProcessName, Name, DeviceName );
Device = AddDevice( DeviceName, DeviceType, DeviceID, DeviceAddr ); DeviceConfig = DeviceConfig->GetNextPeer();
continue;
}
DeviceID = DeviceConfig->GetChInt( "ID", 0 );
DeviceAddr = (char*)DeviceConfig->GetChStr( "Address", NULL );
DeviceType = (char*)DeviceConfig->GetChStr( "Type", NULL );
DataPath = (char*)DeviceConfig->GetChStr( "DataPath", NULL );
Device = AddDevice( DeviceName, DeviceType, DeviceID, DeviceAddr, DataPath );
if (Device) { if (Device) {
InitDeviceParams( Device, DeviceData ); InitDeviceParams( Device, DeviceConfig, Device->DataNode );
InitParamGroups( Device, DeviceData );
} }
DeviceData = DeviceData->GetNextPeer(); DeviceConfig = DeviceConfig->GetNextPeer();
} }
return true; return true;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool CDeviceCore::InitDeviceParams( TDevice * Device, CDataMember * DeviceConfig ) bool CDeviceCore::InitDeviceParams( TDevice * Device, CDataMember * DeviceConfig, CDataMember * ParentNode )
{ {
CDataMember * ParamData; CDataMember * ParamConfig;
CDataMember * InitVal;
TDeviceParam * Param;
TDeviceParam * Template; TDeviceParam * Template;
bool isType = (Device->Name)? false : true;
EDeviceDataType DataType; // Copy Template Params
bool Read;
bool Write;
char * EventOut;
int EventInt;
// Copy Template
Template = (Device->Template)? Device->Template->FirstParam : NULL; Template = (Device->Template)? Device->Template->FirstParam : NULL;
while (Template) while (Template) {
{ CopyTemplateParam( Device, Template, ParentNode );
Template = Template->Next;
}
CopyTemplateParamGroups( Device );
// Read Device Params
ParamConfig = DeviceConfig->GetChFirstChild( "Parameters", true );
while (ParamConfig) {
InitDeviceParam( Device, ParamConfig, NULL, ((isType)? NULL : Device->DataPath), ParentNode, NULL );
ParamConfig = ParamConfig->GetNextPeer();
}
return true;
}
//---------------------------------------------------------------------------
bool CDeviceCore::CopyTemplateParam( TDevice * Device, TDeviceParam * Template, CDataMember * ParentNode )
{
TDeviceParam * Param = NULL;
CDataMember * DataNode = NULL;
char * DataPath = NULL;
if ((Param = AddDeviceParam( Device, Template->Name, Template->DataType, Template->Len ))) if ((Param = AddDeviceParam( Device, Template->Name, Template->DataType, Template->Len )))
{ {
SetParamAccess( Param, Template->Read, Template->Write ); SetParamAccess( Param, Template->Read, Template->Write );
SetParamEvent( Param, (Template->EventChannel)? Template->EventChannel->Name : NULL, Template->EventInterval );
if (Template->DataPath) {
DataPath = (char*)malloc( strlen(Device->DataPath) + strlen(Template->DataPath) + 2);
sprintf( DataPath, "%s/%s", Device->DataPath, Template->DataPath );
DataNode = (Device->DataNode)? Device->DataNode->GetChild( Template->DataPath, true ) : NULL;
SetDataPath( Param, DataPath, DataNode );
}
if ((Template->DataType == dtUnsigned16) || (Template->DataType == dtUnsigned32_HL) || (Template->DataType == dtUnsigned32_LH)) { if ((Template->DataType == dtUnsigned16) || (Template->DataType == dtUnsigned32_HL) || (Template->DataType == dtUnsigned32_LH)) {
UpdateUnsignedValue( Param, *((u_int16_t*)Template->Value), Template->Changed ); UpdateUnsignedValue( Param, *((u_int16_t*)Template->Value), Template->Changed );
@@ -214,26 +263,132 @@ bool CDeviceCore::InitDeviceParams( TDevice * Device, CDataMember * DeviceConfi
if (Template->SetChanged) if (Template->SetChanged)
SetStringValue( Param, (char*)Template->Value, Template->Len, true ); SetStringValue( Param, (char*)Template->Value, Template->Len, true );
} }
}
Template = Template->Next; SetParamEvent( Param, (Template->EventChannel)? Template->EventChannel->Name : NULL, Template->EventInterval );
} }
// Add Parameters if (DataPath) free( DataPath );
ParamData = DeviceConfig->GetChFirstChild( "Parameters", true ); return true;
while (ParamData) }
{ //---------------------------------------------------------------------------
DataType = GetDataType((char*)ParamData->GetChStr( "Type", "Unsigned16", true ));
if ((Param = AddDeviceParam( Device, ParamData->GetName(), DataType, 1 ))) bool CDeviceCore::CopyTemplateParamGroups( TDevice * Device )
{ {
Read = ParamData->GetChBool( "Read", false, true ); TDeviceParamGroup * TemplateGroup;
Write = ParamData->GetChBool( "Write", false, true ); TDeviceParamItem * TemplateItem;
TDeviceParamGroup * ParamGroup;
TDeviceParam * Param;
// Check if Template Groups exists
if (!Device->Template || !(TemplateGroup = Device->Template->FirstParamGroup))
return false;
while (TemplateGroup) {
// Create group
ParamGroup = AddParamGroup( Device, TemplateGroup->Name );
// Add Registers
TemplateItem = TemplateGroup->FirstParam;
while (TemplateItem) {
if ((Param = GetDeviceParam( Device, TemplateItem->Param->Name )))
AddParamItem( ParamGroup, Param );
TemplateItem = TemplateItem->NextItem;
}
TemplateGroup = TemplateGroup->NextGroup;
}
return true;
}
//---------------------------------------------------------------------------
bool CDeviceCore::InitDeviceParam( TDevice * Device, CDataMember * ParamConfig, const char * ParentName,
const char * ParentPath, CDataMember * ParentNode, TDeviceParamGroup * ParentParamGroup )
{
char * NodeName;
char * FullName;
char * DataPath;
CDataMember * DataNode;
CDataMember * Children;
CDataMember * ChildConfig;
CDataMember * ChildMap;
CDataMember * InitVal;
TDeviceParam * Param;
EDeviceDataType DataType;
char * ParamGroupName;
SDeviceParamGroup * ParamGroup;
bool Read;
bool Write;
char * EventOut;
int EventInt;
// Create Node Name
NodeName = (char*)ParamConfig->GetName();
if (ParentName && *ParentName) {
FullName = (char*)malloc( strlen(ParentName) + strlen(NodeName) + 2 );
sprintf( FullName, "%s_%s", ParentName, NodeName );
} else {
FullName = strdup( NodeName );
}
// Create Node Path
DataNode = (ParentNode)? ParentNode->GetChild( NodeName, true ) : NULL;
if (ParentPath && *ParentPath) {
DataPath = (char*)malloc( strlen(ParentPath) + strlen(NodeName) + 2 );
sprintf( DataPath, "%s/%s", ParentPath, NodeName );
} else {
DataPath = strdup( NodeName );
}
if ((Children = ParamConfig->GetChild( "Children", false ))) {
// Data Branch
if ((ParamGroupName = (char*)ParamConfig->GetChStr( "ParamGroup", NULL, false ))) {
ParamGroup = AddParamGroup( Device, ParamGroupName );
} else {
ParamGroup = ParentParamGroup;
}
if (Children->isString()) {
// Load from file
ChildMap = new CDataMember();
JSONparse->SetBase( ChildMap );
if (!JSONparse->ReadFromFile( NULL, Children->GetStr() )) {
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Fail to load parameters from file: '%s'",
ProcessName, Name, Children->GetStr() );
}
else {
ChildConfig = ChildMap->GetFirstChild();
while (ChildConfig) {
InitDeviceParam( Device, ChildConfig, FullName, DataPath, DataNode, ParamGroup );
ChildConfig = ChildConfig->GetNextPeer();
}
}
delete ChildMap;
}
else {
// Load children
ChildConfig = Children->GetFirstChild();
while (ChildConfig) {
InitDeviceParam( Device, ChildConfig, FullName, DataPath, DataNode, ParamGroup );
ChildConfig = ChildConfig->GetNextPeer();
}
}
}
else {
// Data Leaf
DataType = GetDataType((char*)ParamConfig->GetChStr( "Type", "Unsigned16", true ));
if ((Param = AddDeviceParam( Device, FullName, DataType, 1 ))) {
// Leaf
Read = ParamConfig->GetChBool( "Read", false, true );
Write = ParamConfig->GetChBool( "Write", false, true );
SetParamAccess( Param, Read, Write ); SetParamAccess( Param, Read, Write );
EventOut = (char*)ParamData->GetChStr( "EventChannel", NULL, false ); SetDataPath( Param, DataPath, DataNode );
EventInt = ParamData->GetChInt( "EventInterval", 0, false );
SetParamEvent( Param, EventOut, EventInt );
if ((InitVal = ParamData->GetChild( "InitValue", false ))) { if ((InitVal = ParamConfig->GetChild( "InitValue", false ))) {
if ((DataType == dtUnsigned16) || (DataType == dtUnsigned32_HL) || (DataType == dtUnsigned32_LH)) { if ((DataType == dtUnsigned16) || (DataType == dtUnsigned32_HL) || (DataType == dtUnsigned32_LH)) {
UpdateUnsignedValue( Param, InitVal->GetInt(0), Read ); UpdateUnsignedValue( Param, InitVal->GetInt(0), Read );
if (Write) if (Write)
@@ -255,54 +410,23 @@ bool CDeviceCore::InitDeviceParams( TDevice * Device, CDataMember * DeviceConfi
SetStringValue( Param, InitVal->GetStr(""), InitVal->GetLen(), true ); SetStringValue( Param, InitVal->GetStr(""), InitVal->GetLen(), true );
} }
} }
}
// Read + Event Out
ParamData = ParamData->GetNextPeer();
}
return true;
}
//---------------------------------------------------------------------------
bool CDeviceCore::InitParamGroups( TDevice * Device, CDataMember * DeviceConfig ) if ((ParamGroupName = (char*)ParamConfig->GetChStr( "ParamGroup", NULL, false ))) {
{ ParamGroup = AddParamGroup( Device, ParamGroupName );
CDataMember * GroupData; } else {
CDataMember * ItemData; ParamGroup = ParentParamGroup;
TDeviceParamGroup * Group; }
TDeviceParamGroup * GroupTemplate; if (ParamGroup)
TDeviceParamItem * ItemTemplate; AddParamItem( ParamGroup, Param );
// Copy Template EventOut = (char*)ParamConfig->GetChStr( "EventChannel", NULL, false );
GroupTemplate = (Device->Template)? Device->Template->FirstParamGroup : NULL; EventInt = ParamConfig->GetChInt( "EventInterval", 0, false );
while (GroupTemplate) SetParamEvent( Param, EventOut, EventInt );
{
if ((Group = AddParamGroup( Device, GroupTemplate->Name )))
{
ItemTemplate = GroupTemplate->FirstParam;
while (ItemTemplate)
{
AddParamItem( Group, ItemTemplate->Param->Name );
ItemTemplate = ItemTemplate->NextItem;
} }
} }
GroupTemplate = GroupTemplate->NextGroup;
}
// Add Parameters
GroupData = DeviceConfig->GetChFirstChild( "ParamGroups", true );
while (GroupData)
{
if ((Group = AddParamGroup( Device, GroupData->GetName() )))
{
ItemData = GroupData->GetElement( 0 );
while (ItemData)
{
AddParamItem( Group, ItemData->GetStr() );
ItemData = ItemData->GetNextPeer();
}
}
GroupData = GroupData->GetNextPeer();
}
if (FullName) free( FullName );
if (DataPath) free( DataPath );
return true; return true;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -394,7 +518,7 @@ bool CDeviceCore::CheckReplyTimeout()
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
TDevice * CDeviceCore::AddDeviceType( const char * DeviceTypeName ) TDevice * CDeviceCore::AddDeviceType( const char * DeviceTypeName, const char * DataPath )
{ {
TDevice ** DeviceType = GetDeviceTypePtr( DeviceTypeName ); TDevice ** DeviceType = GetDeviceTypePtr( DeviceTypeName );
@@ -410,8 +534,8 @@ TDevice * CDeviceCore::AddDeviceType( const char * DeviceTypeName )
else { else {
*DeviceType = new TDevice; *DeviceType = new TDevice;
(*DeviceType)->Type = (char *)malloc( strlen( DeviceTypeName )+1 ); (*DeviceType)->Type = strdup( DeviceTypeName );
strcpy( (*DeviceType)->Type, DeviceTypeName ); (*DeviceType)->DataPath = strdup( DataPath );
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Added device type '%s'", if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Added device type '%s'",
ProcessName, Name, DeviceTypeName ); ProcessName, Name, DeviceTypeName );
@@ -420,7 +544,8 @@ TDevice * CDeviceCore::AddDeviceType( const char * DeviceTypeName )
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
TDevice * CDeviceCore::AddDevice( const char * DeviceName, const char * DeviceType, const int DeviceID, const char * DeviceAddress ) TDevice * CDeviceCore::AddDevice( const char * DeviceName, const char * DeviceType,
const int DeviceID, const char * DeviceAddress, const char * DataPath )
{ {
TDevice ** Device = &FirstDevice; TDevice ** Device = &FirstDevice;
@@ -454,21 +579,28 @@ TDevice * CDeviceCore::AddDevice( const char * DeviceName, const char * DeviceTy
else { else {
*Device = new TDevice; *Device = new TDevice;
(*Device)->Name = (char *)malloc( strlen( DeviceName )+1 ); (*Device)->Name = strdup( DeviceName );
strcpy( (*Device)->Name, DeviceName );
(*Device)->ID = DeviceID; (*Device)->ID = DeviceID;
if (DeviceAddress) { if (DeviceAddress) {
(*Device)->Address = (char *)malloc( strlen( DeviceAddress )+1 ); (*Device)->Address = strdup( DeviceAddress );
strcpy( (*Device)->Address, DeviceAddress );
} }
if (DeviceType && *DeviceType) { if (DeviceType && *DeviceType) {
(*Device)->Type = (char *)malloc( strlen( DeviceType )+1 ); (*Device)->Type = strdup( DeviceType );
strcpy( (*Device)->Type, DeviceType );
(*Device)->Template = GetDeviceType( DeviceType ); (*Device)->Template = GetDeviceType( DeviceType );
if (DataPath && *DataPath) {
(*Device)->DataPath = strdup( DataPath );
(*Device)->DataNode = ValueTree->GetChild( (*Device)->DataPath, true );
}
else if ((*Device)->Template && (*Device)->Template->DataPath) {
// Use Template path as prefix, then add device ID or address
int PathLen = strlen((*Device)->Template->DataPath) + strlen(DeviceName) + 1;
(*Device)->DataPath = (char*)malloc(PathLen +1);
sprintf( (*Device)->DataPath, "%s/%s", (*Device)->Template->DataPath, DeviceName );
(*Device)->DataNode = ValueTree->GetChild( (*Device)->DataPath, true );
}
} }
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Added device '%s' - Tp:'%s'%s, ID:%d, Addr:'%s'", if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Added device '%s' - Tp:'%s'%s, ID:%d, Addr:'%s'",
@@ -497,6 +629,8 @@ bool CDeviceCore::DestroyDevice( TDevice ** Device )
free( (*Device)->Address ); free( (*Device)->Address );
if ((*Device)->Type) if ((*Device)->Type)
free( (*Device)->Type ); free( (*Device)->Type );
if ((*Device)->DataPath)
free( (*Device)->DataPath );
// Destroy parameters & groups // Destroy parameters & groups
while ((*Device)->FirstParam) { while ((*Device)->FirstParam) {
@@ -540,8 +674,7 @@ TDeviceParam * CDeviceCore::AddDeviceParam( TDevice * Device, const char * Param
*Param = new TDeviceParam; *Param = new TDeviceParam;
// Set Name // Set Name
(*Param)->Name = (char *)malloc( strlen( ParamName )+1 ); (*Param)->Name = strdup( ParamName );
strcpy( (*Param)->Name, ParamName );
(*Param)->DataType = DataType; (*Param)->DataType = DataType;
(*Param)->Device = Device; (*Param)->Device = Device;
@@ -654,6 +787,8 @@ bool CDeviceCore::DestroyDeviceParam( TDeviceParam ** Param )
free( (*Param)->Value ); free( (*Param)->Value );
if ((*Param)->SetValue) if ((*Param)->SetValue)
free( (*Param)->SetValue ); free( (*Param)->SetValue );
if ((*Param)->DataPath)
free( (*Param)->DataPath );
// Destroy Param // Destroy Param
delete *Param; delete *Param;
@@ -683,9 +818,7 @@ TDeviceParamGroup * CDeviceCore::AddParamGroup( TDevice * Device, const char * G
else { else {
*ParamGroup = new TDeviceParamGroup; *ParamGroup = new TDeviceParamGroup;
(*ParamGroup)->Name = (char *)malloc( strlen( GroupName )+1 ); (*ParamGroup)->Name = strdup( GroupName );
strcpy( (*ParamGroup)->Name, GroupName );
(*ParamGroup)->Device = Device; (*ParamGroup)->Device = Device;
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Added param group '%s/%s'", if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Added param group '%s/%s'",
@@ -726,27 +859,20 @@ bool CDeviceCore::DestroyParamGroup( TDeviceParamGroup ** ParamGroup )
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
TDeviceParamItem * CDeviceCore::AddParamItem( TDeviceParamGroup * Group, const char * ParamName ) TDeviceParamItem * CDeviceCore::AddParamItem( TDeviceParamGroup * Group, TDeviceParam * Param )
{ {
TDeviceParamItem ** Item = GetParamItemPtr( Group, ParamName ); TDeviceParamItem ** Item;
TDeviceParam * Param = NULL;
if (!Item) { if (!Param || !(Item = GetParamItemPtr( Group, Param->Name ))) {
// Invalid group/param // Invalid group/param
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Param group item '%s/%s' cannot be created", if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Param group item '%s/%s' cannot be created",
ProcessName, Name, ((!Group)? "[group]" : Group->Name), ((!ParamName)? "[param]" : ParamName)); ProcessName, Name, ((!Group)? "[group]" : Group->Name), ((!Param->Name)? "[param]" : Param->Name));
return NULL; return NULL;
} }
else if (*Item) { else if (*Item) {
// Item already exists // Item already exists
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Param Group item '%s/%s' already exists", if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Param Group item '%s/%s' already exists",
ProcessName, Name, Group->Name, ParamName ); ProcessName, Name, Group->Name, Param->Name );
}
else if (!(Param = GetDeviceParam( Group->Device, ParamName ))) {
// Parameter does not exist
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Param '%s/%s' does not exists - Cannot add to Param group '%s'",
ProcessName, Name, ((Group->Device->Name)? Group->Device->Name : Group->Device->Type),
ParamName, Group->Name );
} }
else { else {
*Item = new TDeviceParamItem; *Item = new TDeviceParamItem;
@@ -760,7 +886,7 @@ TDeviceParamItem * CDeviceCore::AddParamItem( TDeviceParamGroup * Group, const c
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Added param group item '%s/%s/%s'", if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Added param group item '%s/%s/%s'",
ProcessName, Name, ((Group->Device->Name)? Group->Device->Name : Group->Device->Type), ProcessName, Name, ((Group->Device->Name)? Group->Device->Name : Group->Device->Type),
Group->Name, ParamName ); Group->Name, Param->Name );
} }
return *Item; return *Item;
} }
@@ -781,6 +907,23 @@ bool CDeviceCore::DestroyParamItem( TDeviceParamItem ** Item )
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool CDeviceCore::SetDataPath( TDeviceParam * Param, const char * DataPath, CDataMember * DataNode )
{
if (!Param)
return false;
Param->DataPath = strdup( DataPath );
Param->DataNode = DataNode;
if (Log) {
char * DeviceName = (Param->Device->Name)? Param->Device->Name : Param->Device->Type;
Log->Message( LogLevel, dlMedium, "%s/%s: Set param '%s/%s' data ref - P:%s, N:%s",
ProcessName, Name, DeviceName, Param->Name, DataPath, ((DataNode)? DataNode->GetName() : "(none)") );
}
return true;
}
//---------------------------------------------------------------------------
bool CDeviceCore::SetParamAccess( TDeviceParam * Param, bool Read, bool Write ) bool CDeviceCore::SetParamAccess( TDeviceParam * Param, bool Read, bool Write )
{ {
if (!Param) if (!Param)
@@ -834,6 +977,9 @@ bool CDeviceCore::UpdateUnsignedValue( TDeviceParam * Param, const u_int32_t Val
// Set new value & mark change // Set new value & mark change
*((u_int16_t*)Param->Value) = Value; *((u_int16_t*)Param->Value) = Value;
if (Param->DataNode)
Param->DataNode->SetInt( *((u_int16_t*)Param->Value) );
// Mark change & log event // Mark change & log event
Changed = true; Changed = true;
if (Log) { if (Log) {
@@ -851,6 +997,9 @@ bool CDeviceCore::UpdateUnsignedValue( TDeviceParam * Param, const u_int32_t Val
// Set new value & mark change // Set new value & mark change
*((u_int32_t*)Param->Value) = Value; *((u_int32_t*)Param->Value) = Value;
if (Param->DataNode)
Param->DataNode->SetInt( *((u_int32_t*)Param->Value) );
// Mark change & log event // Mark change & log event
Changed = true; Changed = true;
if (Log) { if (Log) {
@@ -869,6 +1018,9 @@ bool CDeviceCore::UpdateUnsignedValue( TDeviceParam * Param, const u_int32_t Val
// Set new value & mark change // Set new value & mark change
*((u_int32_t*)Param->Value) = Value; *((u_int32_t*)Param->Value) = Value;
if (Param->DataNode)
Param->DataNode->SetInt( *((u_int32_t*)Param->Value) );
// Mark change & log event // Mark change & log event
Changed = true; Changed = true;
if (Log) { if (Log) {
@@ -908,6 +1060,9 @@ bool CDeviceCore::UpdateSignedValue( TDeviceParam * Param, const int32_t Value,
// Set new value & mark change // Set new value & mark change
*((int16_t*)Param->Value) = Value; *((int16_t*)Param->Value) = Value;
if (Param->DataNode)
Param->DataNode->SetInt( *((int16_t*)Param->Value) );
// Mark change & log event // Mark change & log event
Changed = true; Changed = true;
if (Log) { if (Log) {
@@ -925,6 +1080,9 @@ bool CDeviceCore::UpdateSignedValue( TDeviceParam * Param, const int32_t Value,
// Set new value & mark change // Set new value & mark change
*((int32_t*)Param->Value) = Value; *((int32_t*)Param->Value) = Value;
if (Param->DataNode)
Param->DataNode->SetInt( *((int32_t*)Param->Value) );
// Mark change & log event // Mark change & log event
Changed = true; Changed = true;
if (Log) { if (Log) {
@@ -965,6 +1123,9 @@ bool CDeviceCore::UpdateFloatValue( TDeviceParam * Param, const float Value, boo
// Set new value & mark change // Set new value & mark change
*((float*)Param->Value) = Value; *((float*)Param->Value) = Value;
if (Param->DataNode)
Param->DataNode->SetFloat( *((float*)Param->Value) );
// Mark change & log event // Mark change & log event
Changed = true; Changed = true;
if (Log) { if (Log) {
@@ -1014,6 +1175,9 @@ bool CDeviceCore::UpdateStringValue( TDeviceParam * Param, const char * Value, c
memset( &((char*)Param->Value)[Len], 0x0, (Param->Len - Len + 1) ); // Add null teriminate memset( &((char*)Param->Value)[Len], 0x0, (Param->Len - Len + 1) ); // Add null teriminate
} }
if (Param->DataNode)
Param->DataNode->SetStr( (char*)Param->Value );
// Mark Change // Mark Change
Changed = true; Changed = true;
if (Log) { if (Log) {
@@ -1197,8 +1361,7 @@ bool CDeviceCore::SetValue( TDeviceParam * Param, const char * Value, const int
{ {
// Ensure string is zero terminated // Ensure string is zero terminated
if (Value[Len] != 0) { if (Value[Len] != 0) {
TempStr = (char *)malloc( Len+1 ); TempStr = strndup( Value, Len );
memcpy( TempStr, Value, Len );
TempStr[Len] = 0; TempStr[Len] = 0;
UseTempStr = true; UseTempStr = true;
} }
@@ -1242,8 +1405,10 @@ bool CDeviceCore::SetValue( TDeviceParam * Param, const char * Value, const int
bool CDeviceCore::GetValue( TDeviceParam * Param, char * Value, int &Len ) bool CDeviceCore::GetValue( TDeviceParam * Param, char * Value, int &Len )
{ {
// Validate // Validate
if (!Param || !Value) if (!Param || !Value) {
Value[0] = 0;
return false; return false;
}
// Check if return value longer than actual value // Check if return value longer than actual value
switch (Param->DataType) switch (Param->DataType)
@@ -1286,6 +1451,7 @@ bool CDeviceCore::GetValue( TDeviceParam * Param, char * Value, int &Len )
break; break;
default : default :
Value[0] = 0;
break; break;
} }
return true; return true;
@@ -1350,7 +1516,12 @@ bool CDeviceCore::GetCmdParam( const char * Start, char * Param, char ** NextPar
int ParamLen; int ParamLen;
// Get length of param // Get length of param
if ((NextDelimeter = strchr( (char*)Start, ',' ))) { if (!Start || !*Start) {
Param[0] = 0;
NextParam = NULL;
return false;
}
else if ((NextDelimeter = strchr( (char*)Start, ',' ))) {
ParamLen = NextDelimeter - Start; ParamLen = NextDelimeter - Start;
*NextParam = NextDelimeter + 1; *NextParam = NextDelimeter + 1;
} }
@@ -1375,162 +1546,147 @@ bool CDeviceCore::GetCmdParam( const char * Start, char * Param, char ** NextPar
int CDeviceCore::HandleCommand( const char *ChannelName, const char * Data, const int MaxLen ) int CDeviceCore::HandleCommand( const char *ChannelName, const char * Data, const int MaxLen )
{ {
int Len; int Len;
char ParamName[50]; char Value[50];
char * NextParam = NULL; char * NextParam = NULL;
TDevice * Device = NULL; TDevice * Device = NULL;
TDeviceParam * Param = NULL; TDeviceParam * Param = NULL;
char OutputStr[250]; char OutputStr[250];
bool Error = false;
// Show accepted input // Show accepted input
Log->Output( LogLevel, dlHigh, loNormal, Data, MaxLen, "%s/%s: Channel '%s' - IN:", Log->Output( LogLevel, dlHigh, loNormal, Data, MaxLen, "%s/%s: Channel '%s' - IN:",
ProcessName, Name, ChannelName ); ProcessName, Name, ChannelName );
// Get command command // Get command command
GetCmdParam( Data, ParamName, &NextParam ); GetCmdParam( Data, Value, &NextParam );
if (!strcasecmp( "get", ParamName )) if (!strcasecmp( "get", Value ))
{ {
// Check for additional parameters // Validate parameters
if (!NextParam) { if (!GetCmdParam( NextParam, Value, &NextParam)) {
// No Parameters strcpy( OutputStr, "- Missing device name" );
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Missing 'get' parameters", Error = true;
ProcessName, Name, ChannelName );
return MaxLen;
} }
else if (!(Device = GetDeviceByName( Value ))) {
// Get device name strcpy( OutputStr, "- Device not found");
GetCmdParam( NextParam, ParamName, &NextParam ); Error = true;
if (!(Device = GetDeviceByName( ParamName ))) {
// Unknown Parameters
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown 'get' Device: '%s'",
ProcessName, Name, ChannelName, ParamName );
return MaxLen;
} }
else if (!GetCmdParam( NextParam, Value, &NextParam )) {
// Get parameter name strcpy( OutputStr, "- Missing parameter name" );
GetCmdParam( NextParam, ParamName, &NextParam ); Error = true;
if (!(Param = GetDeviceParam( Device, ParamName ))) {
// Unknown Parameters
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown 'get' Param: '%s'",
ProcessName, Name, ChannelName, ParamName );
return MaxLen;
} }
else if (!(Param = GetDeviceParam( Device, Value ))) {
// Check for additional parameters strcpy( OutputStr, "- Device parameter not found");
if (NextParam) { Error = true;
// Unused Parameters
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unnecessary 'get' parameters",
ProcessName, Name, ChannelName );
return MaxLen;
} }
else if (NextParam) {
strcpy( OutputStr, "- Too many parameters");
Error = true;
}
else {
sprintf( OutputStr, "> %s,%s = ", Device->Name, Param->Name );
Len = MaxLen - strlen(OutputStr) - 1;
// Build reply if (!GetValue( (TDeviceParam*)Param, &OutputStr[ strlen(OutputStr) ], Len )) {
sprintf( OutputStr, "get,%s,", Param->Name ); strcpy( OutputStr, "- Error getting parameter");
Len = MaxLen - strlen(OutputStr); Error = true;
}
// Insert value else {
if (!GetValue( (TDeviceParam*)Param, &OutputStr[ strlen(OutputStr) ], Len ))
return false;
// Send reply
strcat( OutputStr, "\n" ); strcat( OutputStr, "\n" );
Output( ChannelName, OutputStr, strlen(OutputStr) ); Output( ChannelName, OutputStr, strlen(OutputStr) );
return true;
} }
else if (!strcasecmp( "set", ParamName )) }
// Report error
if (Error) {
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' Get",
ProcessName, Name, ChannelName, OutputStr );
strcat( OutputStr, "\n" );
Output( ChannelName, OutputStr, strlen(OutputStr) );
}
}
else if (!strcasecmp( "set", Value ))
{ {
// Check for additional parameters // Validate parameters
if (!NextParam) { if (!GetCmdParam( NextParam, Value, &NextParam)) {
// No Parameters strcpy( OutputStr, "- Missing device name" );
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Missing 'set' parameters", Error = true;
ProcessName, Name, ChannelName );
return MaxLen;
} }
else if (!(Device = GetDeviceByName( Value ))) {
// Get Device name strcpy( OutputStr, "- Device not found");
GetCmdParam( NextParam, ParamName, &NextParam ); Error = true;
if (!(Device = GetDeviceByName( ParamName ))) {
// Unknown Parameters
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown 'set' Device: '%s'",
ProcessName, Name, ChannelName, ParamName );
return MaxLen;
} }
else if (!GetCmdParam( NextParam, Value, &NextParam )) {
// Get parameter name strcpy( OutputStr, "- Missing parameter name" );
GetCmdParam( NextParam, ParamName, &NextParam ); Error = true;
if (!(Param = GetDeviceParam( Device, ParamName ))) {
// Unknown Parameters
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown 'set' Param: '%s'",
ProcessName, Name, ChannelName, ParamName );
return MaxLen;
} }
else if (!(Param = GetDeviceParam( Device, Value ))) {
// Get parameter value strcpy( OutputStr, "- Device parameter not found");
GetCmdParam( NextParam, ParamName, &NextParam ); Error = true;
if (strlen(ParamName) == 0) {
// No Parameters
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - No 'set' value parameter",
ProcessName, Name, ChannelName );
return MaxLen;
} }
else if (!GetCmdParam( NextParam, Value, &NextParam )) {
// Check for additional parameters strcpy( OutputStr, "- Missing set value");
if (NextParam) { Error = true;
// Unused Parameters
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unnecessary 'set' parameters",
ProcessName, Name, ChannelName );
return MaxLen;
} }
else if (NextParam) {
// Set value strcpy( OutputStr, "- Too many parameters");
Len = MaxLen; Error = true;
if (!SetValue( Param, ParamName, Len, true )) }
return false; else {
if (!SetValue( Param, Value, strlen(Value), true )) {
// Build & send reply strcpy( OutputStr, "- Error seting parameter");
sprintf( OutputStr, "set,%s,%s\n", Param->Name, ParamName ); Error = true;
}
else {
sprintf( OutputStr, "> set %s,%s = %s\n", Device->Name, Param->Name, Value );
Output( ChannelName, OutputStr ); Output( ChannelName, OutputStr );
return true;
} }
else if (!strcasecmp( "status", ParamName )) }
// Report error
if (Error) {
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' Set",
ProcessName, Name, ChannelName, OutputStr );
strcat( OutputStr, "\n" );
Output( ChannelName, OutputStr, strlen(OutputStr) );
}
}
else if (!strcasecmp( "status", Value ))
{ {
// Check for additional parameters // Validate parameters
if (!NextParam) { if (!GetCmdParam( NextParam, Value, &NextParam)) {
// No Parameters strcpy( OutputStr, "- Missing device name" );
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Missing 'status' parameters", Error = true;
ProcessName, Name, ChannelName );
return MaxLen;
} }
else if (!(Device = GetDeviceByName( Value ))) {
// Get Device name strcpy( OutputStr, "- Device not found");
GetCmdParam( NextParam, ParamName, &NextParam ); Error = true;
if (!(Device = GetDeviceByName( ParamName ))) {
// Unknown Parameters
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown 'status' Device: '%s'",
ProcessName, Name, ChannelName, ParamName );
return MaxLen;
} }
else if (NextParam) {
// Check for additional parameters strcpy( OutputStr, "- Too many parameters");
if (NextParam) { Error = true;
// Unused Parameters
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unnecessary 'status' parameters",
ProcessName, Name, ChannelName );
return MaxLen;
} }
else {
// Build & send reply sprintf( OutputStr, "> %s - %s\n", Device->Name, ((Device->Online)? "online" : "offline") );
sprintf( OutputStr, "status,%s,%d\n", Device->Name, Device->Online );
Output( ChannelName, OutputStr ); Output( ChannelName, OutputStr );
return true; }
// Report error
if (Error) {
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' Status",
ProcessName, Name, ChannelName, OutputStr );
strcat( OutputStr, "\n" );
Output( ChannelName, OutputStr, strlen(OutputStr) );
}
} }
else else
{ {
// Unrecognised command // Unrecognised command
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unrecognized command: '%s'", strcpy( OutputStr, "- Unknown command");
ProcessName, Name, ChannelName, ParamName ); Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s', %s%s",
return MaxLen; ProcessName, Name, ChannelName, Value, OutputStr );
strcat( OutputStr, " (comma separated values)\n" );
Output( ChannelName, OutputStr, strlen(OutputStr) );
} }
return MaxLen; return MaxLen;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -31,8 +31,8 @@ const char DataTypeName[][20] = { "None", "Unsigned16", "Signed16", "Unsigned32_
// Structure prototypes // Structure prototypes
typedef struct SDevice TDevice; typedef struct SDevice TDevice;
typedef struct SDeviceParam TDeviceParam; typedef struct SDeviceParam TDeviceParam;
typedef struct SDeviceParamGroup TDeviceParamGroup; typedef struct SDeviceParamGroup TDeviceParamGroup; // Parameter group, e.g. used with polling parameters
typedef struct SDeviceParamItem TDeviceParamItem; typedef struct SDeviceParamItem TDeviceParamItem; // Placeholder parameters in Parameter groups
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -42,6 +42,8 @@ struct SDevice {
char * Name = NULL; char * Name = NULL;
int ID = 0; int ID = 0;
char * Address = NULL; char * Address = NULL;
char * DataPath = NULL;
CDataMember * DataNode = NULL;
// Device Type // Device Type
char * Type = NULL; char * Type = NULL;
@@ -65,6 +67,10 @@ struct SDeviceParam {
EDeviceDataType DataType = dtNone; EDeviceDataType DataType = dtNone;
TDevice * Device = Device; TDevice * Device = Device;
// Data Path
char * DataPath = NULL;
CDataMember * DataNode = NULL;
// Last value (received from device) // Last value (received from device)
void * Value = NULL; void * Value = NULL;
int Len = 0; int Len = 0;
@@ -117,6 +123,7 @@ protected:
// Configuration // Configuration
CDataMember * Config = NULL; CDataMember * Config = NULL;
CDataMember * ConfigTypes = NULL; CDataMember * ConfigTypes = NULL;
CDataMember * ValueTree = NULL;
CJSONparse * JSONparse = NULL; CJSONparse * JSONparse = NULL;
bool DeviceInit = false; bool DeviceInit = false;
@@ -131,6 +138,7 @@ protected:
TChannel * EventChannel = NULL; TChannel * EventChannel = NULL;
// Poll // Poll
int PollCycle; // Device Polling state, e.g. Init, Connect, Run, Disonnect, Shutdown
int PollStep; // Position in polling sequence int PollStep; // Position in polling sequence
timeval PollWait; // Time at which last poll was done timeval PollWait; // Time at which last poll was done
long PollInterval; // Minimum delay between polls long PollInterval; // Minimum delay between polls
@@ -224,6 +232,11 @@ protected:
Param = &((*Param)->Next); Param = &((*Param)->Next);
return Param; return Param;
} }
inline TDeviceParamGroup * GetNextParamGroup( TDevice * Device, TDeviceParamGroup * LastParamGroup = NULL ) {
if (!Device) return NULL;
TDeviceParamGroup * ParamGroup = (LastParamGroup)? LastParamGroup->NextGroup : Device->FirstParamGroup;
return ParamGroup;
}
inline TDeviceParam * GetNextReadParam( TDevice * Device, TDeviceParam * LastParam = NULL ) { inline TDeviceParam * GetNextReadParam( TDevice * Device, TDeviceParam * LastParam = NULL ) {
if (!Device) return NULL; if (!Device) return NULL;
TDeviceParam * Param = (LastParam)? LastParam->Next : Device->FirstParam; TDeviceParam * Param = (LastParam)? LastParam->Next : Device->FirstParam;
@@ -306,25 +319,30 @@ public:
// Configuration // Configuration
virtual bool Init( CDataMember * FunctionConfig ); virtual bool Init( CDataMember * FunctionConfig );
virtual bool InitDevices( CDataMember * FunctionConfig ); virtual bool InitDevices( CDataMember * FunctionConfig );
virtual bool InitDeviceParams( TDevice * Device, CDataMember * DeviceConfig ); virtual bool InitDeviceParams( TDevice * Device, CDataMember * DeviceConfig, CDataMember * ParentNode );
virtual bool InitParamGroups( TDevice * Device, CDataMember * DeviceConfig ); virtual bool CopyTemplateParam( TDevice * Device, TDeviceParam * Template, CDataMember * ParentNode );
virtual bool CopyTemplateParamGroups( TDevice * Device );
virtual bool InitDeviceParam( TDevice * Device, CDataMember * ParamConfig, const char * ParentName,
const char * ParentPath, CDataMember * ParentNode, TDeviceParamGroup * ParentParamGroup );
// Polling parameters // Polling parameters
bool SetPollParam( int pPollInterval ); bool SetPollParam( int pPollInterval );
bool SetReplyParam( int pReplyTimeout, int pMaxRetries ); bool SetReplyParam( int pReplyTimeout, int pMaxRetries );
bool SetDataPath( TDeviceParam * Param, const char * DataPath, CDataMember * DataNode );
bool SetParamAccess( TDeviceParam * Param, bool Read, bool Write ); bool SetParamAccess( TDeviceParam * Param, bool Read, bool Write );
bool SetParamEvent( TDeviceParam * Param, const char * ChannelName, long pEventInterval ); bool SetParamEvent( TDeviceParam * Param, const char * ChannelName, long pEventInterval );
// Manage Devices Types // Manage Devices Types
TDevice * AddDeviceType( const char * DeviceTypeName ); TDevice * AddDeviceType( const char * DeviceTypeName, const char * DataPath );
inline bool DestroyDeviceType( const char * DeviceTypeName ) { inline bool DestroyDeviceType( const char * DeviceTypeName ) {
TDevice ** DeviceType = GetDeviceTypePtr(DeviceTypeName); TDevice ** DeviceType = GetDeviceTypePtr(DeviceTypeName);
return (DeviceType)? DestroyDevice( DeviceType ) : false; return (DeviceType)? DestroyDevice( DeviceType ) : false;
} }
// Manage Devices // Manage Devices
TDevice * AddDevice( const char * DeviceName, const char * Type = NULL, const int ID = 0, const char * Address = NULL ); TDevice * AddDevice( const char * DeviceName, const char * Type = NULL,
const int ID = 0, const char * Address = NULL, const char * DataPath = NULL );
inline bool DestroyDevice( const char * DeviceName ) { inline bool DestroyDevice( const char * DeviceName ) {
TDevice ** Device = GetDevicePtrByName(DeviceName); TDevice ** Device = GetDevicePtrByName(DeviceName);
return (Device)? DestroyDevice( Device ) : false; return (Device)? DestroyDevice( Device ) : false;
@@ -343,7 +361,7 @@ public:
TDeviceParamGroup ** Group = GetParamGroupPtr( Device, GroupName ); TDeviceParamGroup ** Group = GetParamGroupPtr( Device, GroupName );
return (Group)? DestroyParamGroup( Group ) : false; return (Group)? DestroyParamGroup( Group ) : false;
}; };
TDeviceParamItem * AddParamItem( TDeviceParamGroup * Group, const char * ParamName ); TDeviceParamItem * AddParamItem( TDeviceParamGroup * Group, TDeviceParam * Param );
inline bool DestroyParamItem( TDevice * Device, TDeviceParamGroup * Group, const char * ParamName ) { inline bool DestroyParamItem( TDevice * Device, TDeviceParamGroup * Group, const char * ParamName ) {
TDeviceParamItem ** Item = GetParamItemPtr( Group, ParamName ); TDeviceParamItem ** Item = GetParamItemPtr( Group, ParamName );
return (Item)? DestroyParamItem( Item ) : false; return (Item)? DestroyParamItem( Item ) : false;

View File

@@ -73,58 +73,18 @@ TEventEntry * CreateEvent( const char * EventType, const char * Parent, const
// Create Blank Event Entry // Create Blank Event Entry
Event = CreateEvent(); Event = CreateEvent();
// Set Event type // Set Event params
Event->EventType = (char*)malloc( sizeof(char)*(strlen(EventType)+1) ); Event->EventType = (EventType)? strdup( EventType ) : strdup( "" );
strcpy( Event->EventType, EventType ); Event->Parent = (Parent)? strdup( Parent ) : strdup( "" );
Event->DeviceName = (DeviceName)? strdup( DeviceName ) : strdup( "" );
// Set Parent Name Event->ParamName = (ParamName)? strdup( ParamName ) : strdup( "" );
if (Parent && Parent[0]) Event->Value = (Value)? strdup( Value ) : strdup( "" );
{ Event->SourceName = (SourceName)? strdup( SourceName ) : strdup( "" );
Event->Parent = (char*)malloc( sizeof(char)*(strlen(Parent)+1) );
strcpy( Event->Parent, Parent );
}
else
{
Event->Parent = (char*)malloc(1);
Event->Parent[0] = 0;
}
// Set Device name
Event->DeviceName = (char*)malloc( sizeof(char)*(strlen(DeviceName)+1) );
strcpy( Event->DeviceName, DeviceName );
// Set Param name
if ((!ParamName || !ParamName[0]))
{
Event->ParamName = (char*)malloc(1);
Event->ParamName[0] = 0;
}
else
{
Event->ParamName = (char*)malloc( sizeof(char)*(strlen(ParamName)+1) );
strcpy( Event->ParamName, ParamName );
}
// Set Value
if ((!Value || !Value[0]))
{
Event->Value = (char*)malloc(1);
Event->Value[0] = 0;
}
else
{
Event->Value = (char*)malloc( sizeof(char)*(strlen(Value)+1) );
strcpy( Event->Value, Value );
}
// Set Date and time // Set Date and time
strncpy( Event->DateTime, DateTimeStr, 19); strncpy( Event->DateTime, DateTimeStr, 19);
Event->DateTime[19] = 0; Event->DateTime[19] = 0;
// Set source
Event->SourceName = (char*)malloc( sizeof(char)*(strlen(SourceName)+1) );
strcpy( Event->SourceName, SourceName );
// Return Event // Return Event
return Event; return Event;
} }
@@ -144,57 +104,15 @@ TEventEntry * CopyEvent( TEventEntry * Event )
// Copy event no // Copy event no
EventCopy->EventNo = Event->EventNo; EventCopy->EventNo = Event->EventNo;
// Copy pointer content EventCopy->EventType = (Event->EventType)? strdup( Event->EventType ) : NULL;
if (Event->EventType) EventCopy->Parent = (Event->Parent)? strdup( Event->Parent ) : NULL;
{ EventCopy->DeviceName = (Event->DeviceName)? strdup( Event->DeviceName ) : NULL;
EventCopy->EventType = (char*)malloc( strlen(Event->EventType)+1 ); EventCopy->ParamName = (Event->ParamName)? strdup( Event->ParamName ) : NULL;
strcpy( EventCopy->EventType, Event->EventType ); EventCopy->Value = (Event->Value)? strdup( Event->Value ) : NULL;
} EventCopy->SourceName = (Event->SourceName)? strdup( Event->SourceName ) : NULL;
else
EventCopy->EventType = NULL;
if (Event->Parent)
{
EventCopy->Parent = (char*)malloc( strlen(Event->Parent)+1 );
strcpy( EventCopy->Parent, Event->Parent );
}
else
EventCopy->Parent = NULL;
if (Event->DeviceName)
{
EventCopy->DeviceName = (char*)malloc( strlen(Event->DeviceName)+1 );
strcpy( EventCopy->DeviceName, Event->DeviceName );
}
else
EventCopy->DeviceName = NULL;
if (Event->ParamName)
{
EventCopy->ParamName = (char*)malloc( strlen(Event->ParamName)+1 );
strcpy( EventCopy->ParamName, Event->ParamName );
}
else
EventCopy->ParamName = NULL;
if (Event->Value)
{
EventCopy->Value = (char*)malloc( strlen(Event->Value)+1 );
strcpy( EventCopy->Value, Event->Value );
}
else
EventCopy->Value = NULL;
strcpy( EventCopy->DateTime, Event->DateTime ); strcpy( EventCopy->DateTime, Event->DateTime );
if (Event->SourceName)
{
EventCopy->SourceName = (char*)malloc( strlen(Event->SourceName)+1 );
strcpy( EventCopy->SourceName, Event->SourceName );
}
else
EventCopy->SourceName = NULL;
// Return copy // Return copy
return EventCopy; return EventCopy;
} }
@@ -290,8 +208,7 @@ bool CEventBuffer::SetEventFilter( int n, ... )
// Copy name // Copy name
EventName = va_arg(EventList, char*); EventName = va_arg(EventList, char*);
(*EventType)->Name = (char*)malloc( strlen(EventName)+1 ); (*EventType)->Name = strdup( EventName );
strcpy( (*EventType)->Name, EventName );
// Next // Next
(*EventType)->Next = NULL; (*EventType)->Next = NULL;

View File

@@ -80,10 +80,8 @@ TFileHandle * CFileCore::AddFile( const char * Name, const char * Path, bool Ap
*FileHandle = (TFileHandle*)calloc( 1, sizeof(TFileHandle) ); *FileHandle = (TFileHandle*)calloc( 1, sizeof(TFileHandle) );
// Set name & Path // Set name & Path
(*FileHandle)->Name = (char*)malloc( strlen(Name)+1 ); (*FileHandle)->Name = strdup( Name );
strcpy( (*FileHandle)->Name, Name ); (*FileHandle)->Path = strdup( Path );
(*FileHandle)->Path = (char*)malloc( strlen(Path)+1 );
strcpy( (*FileHandle)->Path, Path );
} }
// Create Channel if necessary // Create Channel if necessary

View File

@@ -31,8 +31,7 @@ CFunctionCore::CFunctionCore( const char * pName, const char * pType ) : Type( p
{ {
// Set name // Set name
if (pName) { if (pName) {
Name = (char*)malloc( strlen(pName)+1 ); Name = strdup( pName );
strcpy( Name, pName );
} }
// Logging // Logging
@@ -195,8 +194,7 @@ TChannel * CFunctionCore::AddChannel( const char * ChannelName, const bool pInpu
*Channel = new TChannel; *Channel = new TChannel;
// Set Name // Set Name
(*Channel)->Name = (char*)malloc( strlen(ChannelName)+1 ); (*Channel)->Name = strdup( ChannelName );
strcpy( (*Channel)->Name, ChannelName );
// Log Event // Log Event
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Channel '%s' - Created", if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Channel '%s' - Created",
@@ -237,8 +235,7 @@ bool CFunctionCore::LinkInputChannel( const char * ChannelName, const char * Out
// Set Parameters // Set Parameters
(*LinkedChannel)->Function = OutFunction; (*LinkedChannel)->Function = OutFunction;
(*LinkedChannel)->Name = (char*)malloc( strlen(OutChannelName)+1 ); (*LinkedChannel)->Name = strdup( OutChannelName );
strcpy( (*LinkedChannel)->Name, OutChannelName );
// Log Event // Log Event
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Input Linked - '%s'/'%s' <-- '%s'/'%s'", if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Input Linked - '%s'/'%s' <-- '%s'/'%s'",
@@ -282,8 +279,7 @@ bool CFunctionCore::LinkOutputChannel( const char * ChannelName, const char * In
// Set Parameters // Set Parameters
(*LinkedChannel)->Function = InFunction; (*LinkedChannel)->Function = InFunction;
(*LinkedChannel)->Name = (char*)malloc( strlen(InChannelName)+1 ); (*LinkedChannel)->Name = strdup( InChannelName );
strcpy( (*LinkedChannel)->Name, InChannelName );
// Log Event // Log Event
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Output Linked - '%s'/'%s' --> '%s'/'%s'", if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Output Linked - '%s'/'%s' --> '%s'/'%s'",

View File

@@ -60,6 +60,7 @@ protected:
// Function Definition // Function Definition
const char * Type = NULL; const char * Type = NULL;
char * Name = NULL; char * Name = NULL;
bool WaitToTerminate = false;
// Channels // Channels
TChannel * FirstChannel = NULL; TChannel * FirstChannel = NULL;
@@ -138,6 +139,8 @@ public:
virtual bool LinkInputChannel( const char * ChannelName, const char * OutFunctionName, const char * OutChannelName, bool Bidirectional ); virtual bool LinkInputChannel( const char * ChannelName, const char * OutFunctionName, const char * OutChannelName, bool Bidirectional );
virtual bool LinkOutputChannel( const char * ChannelName, const char * InFunctionName, const char * InChannelName, bool Bidirectional ); virtual bool LinkOutputChannel( const char * ChannelName, const char * InFunctionName, const char * InChannelName, bool Bidirectional );
virtual bool Process() = 0; virtual bool Process() = 0;
friend class CApplication;
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -15,31 +15,16 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
CJSONparse::CJSONparse()
{
SetBase( NULL );
}
//---------------------------------------------------------------------------
CJSONparse::CJSONparse( CDataMember * pDataTree ) CJSONparse::CJSONparse( CDataMember * pDataTree )
{ {
// Object tree if (!SetBase( pDataTree ))
DataTree = pDataTree; DataTree = NULL;
// File Operation
InputHandle = -1;
OutputHandle = -1;
Buffer = NULL;
// Parsing operation
BufPos = NULL;
Mark = NULL;
LineNo = 0;
CharNo = 0;
RefillBuffer = false;
// Printing operation
Spacer[0] = 0;
SpacerLen = 0;
// Error reporting
Error = false;
ErrorText[0] = 0;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -52,6 +37,18 @@ CJSONparse::~CJSONparse()
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool CJSONparse::SetBase( CDataMember * Object )
{
// Validate
if (Object && !Object->isObject() && !Object->isNull())
return false;
// Set
DataTree = Object;
return true;
}
//---------------------------------------------------------------------------
bool CJSONparse::WriteToScreen( const char * BasePath, const int Indent ) bool CJSONparse::WriteToScreen( const char * BasePath, const int Indent )
{ {
// Print to screen // Print to screen
@@ -124,6 +121,8 @@ bool CJSONparse::WriteToHandle( const char * BasePath, const int Handle, const i
// Validate // Validate
if (!DataTree) { if (!DataTree) {
Error = true;
sprintf( ErrorText, "No Data Tree set" );
return false; return false;
} }
@@ -187,11 +186,6 @@ bool CJSONparse::ReadFromFile( const char * BasePath, const char * FilePath )
int Handle = -1; int Handle = -1;
bool result = false; bool result = false;
// Validate
if (!DataTree) {
return false;
}
// Clear Error // Clear Error
Error = false; Error = false;
@@ -283,7 +277,14 @@ bool CJSONparse::ReadFromBuffer( const char * BasePath )
CDataMember * BaseMember = NULL; CDataMember * BaseMember = NULL;
// Validate // Validate
if (!DataTree || !Buffer) { if (!DataTree) {
Error = true;
sprintf( ErrorText, "No Data Tree set" );
return false;
}
if (!Buffer) {
Error = true;
sprintf( ErrorText, "No Data Buffer defined" );
return false; return false;
} }

View File

@@ -21,28 +21,28 @@
class CJSONparse class CJSONparse
{ {
private: private:
CDataMember * DataTree; CDataMember * DataTree = NULL;
// File operation // File operation
int InputHandle; int InputHandle = -1;
int OutputHandle; int OutputHandle = -1;
CShiftBuffer * Buffer; CShiftBuffer * Buffer = NULL;
// Parsing operation // Parsing operation
char * BufPos; char * BufPos = NULL;
char * Mark; char * Mark = NULL;
int LineNo; int LineNo = 0;
int CharNo; int CharNo = 0;
bool RefillBuffer; bool RefillBuffer = false;
// Printing Operation // Printing Operation
char Spacer[100]; char Spacer[100] = "";
int SpacerLen; int SpacerLen = 0;
// Error // Error
bool Error; bool Error = false;
char ErrorText[100]; char ErrorText[100] = "";
// Parsing functions // Parsing functions
void SkipWhiteSpace(); void SkipWhiteSpace();
@@ -57,9 +57,13 @@ private:
bool PrintArray( CDataMember * Object, const int Indent ); bool PrintArray( CDataMember * Object, const int Indent );
public: public:
CJSONparse();
CJSONparse( CDataMember * pDataTree ); CJSONparse( CDataMember * pDataTree );
~CJSONparse(); ~CJSONparse();
// Tree
bool SetBase( CDataMember * Object );
// Buffer operation // Buffer operation
bool CreateBuffer( int pBufLen ); bool CreateBuffer( int pBufLen );
bool FillBuffer(); bool FillBuffer();

View File

@@ -63,6 +63,27 @@ CSelectableBare::~CSelectableBare()
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
CDataMember * CSelectableBare::GetHandleAddress( THandle * Handle, const char * HandleRef )
{
CDataMember * AddressDef = NULL;
char NamePath[100];
char * Address;
// Handle renamed?
sprintf( NamePath, "Application/Addresses/Rename/%s", HandleRef );
if (!(Address = (char*)Application->Config->GetChStr( NamePath, NULL, false ))) {
Address = (char*)HandleRef;
}
// Get address def
if ((AddressDef = Application->AddressList->GetChild( Address ))) {
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Use address '%s' ('%s')",
ProcessName, Name, Handle->Name, Address, HandleRef );
}
return AddressDef;
}
//---------------------------------------------------------------------------
THandle * CSelectableBare::CreateHandle( const char * HandleName, bool CreateChannel ) THandle * CSelectableBare::CreateHandle( const char * HandleName, bool CreateChannel )
{ {
THandle ** Handle = NULL; THandle ** Handle = NULL;

View File

@@ -44,9 +44,6 @@ CSelectableCore::CSelectableCore( const char * pName, const char * pType ) : CSe
{ {
// Quick access // Quick access
Selector = Application->Selector; Selector = Application->Selector;
// Handles
FirstHandle = NULL;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -98,6 +95,7 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
Handle = CreateHandle( HandleConfig->GetName(), false ); Handle = CreateHandle( HandleConfig->GetName(), false );
Handle->Channel = GetChannel( HandleConfig->GetChStr( "Channel" ) ); Handle->Channel = GetChannel( HandleConfig->GetChStr( "Channel" ) );
// Load handle specifics
Type = (char*)HandleConfig->GetChStr( "Type", "TCPclient", true ); Type = (char*)HandleConfig->GetChStr( "Type", "TCPclient", true );
if (!strcasecmp( Type, "Serial" )) if (!strcasecmp( Type, "Serial" ))
{ {
@@ -130,6 +128,8 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
FlowCtrl = HW_FLOWCTRL; FlowCtrl = HW_FLOWCTRL;
else if (!strcasecmp( FlowCtrlText, "software" )) else if (!strcasecmp( FlowCtrlText, "software" ))
FlowCtrl = SW_FLOWCTRL; FlowCtrl = SW_FLOWCTRL;
else if (!strcasecmp( FlowCtrlText, "rs485" ))
FlowCtrl = RS485_FLOWCTRL;
else else
FlowCtrl = NO_FLOWCTRL; FlowCtrl = NO_FLOWCTRL;
@@ -142,7 +142,7 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
} }
else if (!strcasecmp( Type, "LinePrinter" )) else if (!strcasecmp( Type, "LinePrinter" ))
{ {
if ((Name = (char*)HandleConfig->GetChStr( "Port/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) { if ((Name = (char*)HandleConfig->GetChStr( "Port/Name", NULL )) && (AddressDef = GetHandleAddress( Handle, Name ))) {
Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value
} else { } else {
Address = (char*)HandleConfig->GetChStr( "Port/Address", NULL, true ); // Get default value Address = (char*)HandleConfig->GetChStr( "Port/Address", NULL, true ); // Get default value
@@ -151,7 +151,7 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
} }
else if (!strcasecmp( Type, "UNIXserver" )) else if (!strcasecmp( Type, "UNIXserver" ))
{ {
if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) { if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = GetHandleAddress( Handle, Name ))) {
Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value
} else { } else {
Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
@@ -161,7 +161,7 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
} }
else if (!strcasecmp( Type, "UNIXclient" )) else if (!strcasecmp( Type, "UNIXclient" ))
{ {
if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) { if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = GetHandleAddress( Handle, Name ))) {
Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value
} else { } else {
Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
@@ -170,7 +170,7 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
} }
else if (!strcasecmp( Type, "UDPserver" )) else if (!strcasecmp( Type, "UDPserver" ))
{ {
if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) { if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = GetHandleAddress( Handle, Name ))) {
Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value
Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value
} else { } else {
@@ -182,7 +182,7 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
} }
else if (!strcasecmp( Type, "UDPclient" )) else if (!strcasecmp( Type, "UDPclient" ))
{ {
if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) { if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = GetHandleAddress( Handle, Name ))) {
Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value
Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value
} else { } else {
@@ -194,7 +194,7 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
} }
else if (!strcasecmp( Type, "TCPserver" )) else if (!strcasecmp( Type, "TCPserver" ))
{ {
if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) { if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = GetHandleAddress( Handle, Name ))) {
Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value
Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value
} else { } else {
@@ -207,7 +207,7 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
} }
else if (!strcasecmp( Type, "TCPclient" )) else if (!strcasecmp( Type, "TCPclient" ))
{ {
if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) { if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = GetHandleAddress( Handle, Name ))) {
Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value
Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value
} else { } else {
@@ -253,14 +253,9 @@ bool CSelectableCore::SetSerialHandle( THandle * Handle, const char * FileName )
// Set Type // Set Type
Handle->Type = ctSerial; Handle->Type = ctSerial;
// Clear File Name // Set path
if (Handle->Path) { if (Handle->Path) free( Handle->Path );
free( Handle->Path ); Handle->Path = strdup( FileName );
}
// Set name
Handle->Path = (char*)malloc( strlen(FileName)+1 );
strcpy( Handle->Path, FileName );
// Log event // Log event
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Set as Port [%s]", if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Set as Port [%s]",
@@ -298,14 +293,9 @@ bool CSelectableCore::SetLinePrinterHandle( THandle * Handle, const char * FileN
// Set Type // Set Type
Handle->Type = ctLinePrinter; Handle->Type = ctLinePrinter;
// Clear File Name // Set Path
if (Handle->Path) { if (Handle->Path) free( Handle->Path );
free( Handle->Path ); Handle->Path = strdup( FileName );
}
// Set name
Handle->Path = (char*)malloc( strlen(FileName)+1 );
strcpy( Handle->Path, FileName );
// Log event // Log event
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Set as Port [%s]", if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Set as Port [%s]",
@@ -324,14 +314,9 @@ bool CSelectableCore::SetForkPipeHandle( THandle * Handle, const char * ExecPath
// Set Type // Set Type
Handle->Type = ctForkPipe; Handle->Type = ctForkPipe;
// Clear File Name // Set path
if (Handle->Path) { if (Handle->Path) free( Handle->Path );
free( Handle->Path ); Handle->Path = strdup( ExecPath );
}
// Set name
Handle->Path = (char*)malloc( strlen(ExecPath)+1 );
strcpy( Handle->Path, ExecPath );
// Log event // Log event
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Set as ForkPipe [%s]", if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Set as ForkPipe [%s]",
@@ -358,8 +343,7 @@ bool CSelectableCore::SetUnixHandle( THandle * Handle, EConnectType Type, const
} }
// Set name // Set name
Handle->Path = (char*)malloc( strlen(FileName)+1 ); Handle->Path = strdup( FileName );
strcpy( Handle->Path, FileName );
Handle->Queue = Queue; Handle->Queue = Queue;
// Log event // Log event
@@ -391,11 +375,8 @@ bool CSelectableCore::SetSocketHandle( THandle * Handle, EConnectType Type, con
freeaddrinfo( Handle->AddressList ); freeaddrinfo( Handle->AddressList );
// Set HostName & Port // Set HostName & Port
Handle->HostName = (char*)malloc( strlen(HostName)+1 ); Handle->HostName = strdup( HostName );
strcpy( Handle->HostName, HostName ); Handle->PortName = strdup( PortName );
Handle->PortName = (char*)malloc( strlen(PortName)+1 );
strcpy( Handle->PortName, PortName );
Handle->AddressList = NULL; Handle->AddressList = NULL;
Handle->AddressInfo = NULL; Handle->AddressInfo = NULL;
@@ -437,6 +418,12 @@ THandle * CSelectableCore::OpenSerialPort( THandle * Handle )
return NULL; return NULL;
} }
// Set Send Enable (via RTS) for RS485
if ((Handle->Type == ctSerial) && (Handle->FlowCtrl == RS485_FLOWCTRL)) {
int sercmd = TIOCM_RTS;
ioctl( Handle->FD, TIOCMBIS, &sercmd );
}
// Log Event // Log Event
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Serial Port opened [%s]", if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Serial Port opened [%s]",
ProcessName, Name, Handle->Name, Handle->Path ); ProcessName, Name, Handle->Name, Handle->Path );
@@ -1533,6 +1520,12 @@ bool CSelectableCore::Close( THandle * Handle, bool QuickReopen )
} }
} }
// Set Send Enable (via RTS) for RS485
if ((Handle->Type == ctSerial) && (Handle->FlowCtrl == RS485_FLOWCTRL)) {
int sercmd = TIOCM_RTS;
ioctl( Handle->FD, TIOCMBIC, &sercmd );
}
// Close Handle // Close Handle
if (Handle->Type == ctUDPremote) { if (Handle->Type == ctUDPremote) {
Fail = false; Fail = false;
@@ -1884,10 +1877,22 @@ bool CSelectableCore::Write( THandle * Handle )
{ {
// Write directly to handle / socket // Write directly to handle / socket
errno = 0; errno = 0;
if ((Handle->Type == ctUDPclient)|| (Handle->Type == ctUDPremote)) { if ((Handle->Type == ctUDPclient) || (Handle->Type == ctUDPremote)) {
Len = Handle->OutBuffer->Peek( &Data ); Len = Handle->OutBuffer->Peek( &Data );
BytesWritten = WriteToUDP( Handle, Data, Len, true ); BytesWritten = WriteToUDP( Handle, Data, Len, true );
} }
else if ((Handle->Type == ctSerial) && (Handle->FlowCtrl == RS485_FLOWCTRL)) {
// Set Send Enable (via RTS pin) when sending data
int sercmd = TIOCM_RTS;
ioctl( Handle->FD, TIOCMBIC, &sercmd );
usleep( 1000 );
BytesWritten = Handle->OutBuffer->WriteToFD( Handle->FD );
tcdrain( Handle->FD );
usleep( 1000 );
ioctl( Handle->FD, TIOCMBIS, &sercmd );
}
else { else {
BytesWritten = Handle->OutBuffer->WriteToFD( Handle->FD ); BytesWritten = Handle->OutBuffer->WriteToFD( Handle->FD );
} }
@@ -2143,20 +2148,18 @@ bool CSelectableCore::Process()
{ {
THandle * Handle = NULL; THandle * Handle = NULL;
// Check all handles // Process all Handles
Handle = FirstHandle; Handle = FirstHandle;
while (Handle) while (Handle)
{ {
// Auto manage handles // Auto manage handles
if ((Handle->State == csOpenRequest)) if ((Handle->State == csOpenRequest)) {
{
// Resolve then open socket // Resolve then open socket
if (Timeout( Handle->LastAction, Handle->ResolveDelay )) { if (Timeout( Handle->LastAction, Handle->ResolveDelay )) {
Open( Handle, false ); Open( Handle, false );
} }
} }
else if (((Handle->State != csOpen) && Handle->AutoManage && Handle->Persistent) ) else if (((Handle->State != csOpen) && Handle->AutoManage && Handle->Persistent) ) {
{
// Try to re-open port after delay // Try to re-open port after delay
if (Timeout( Handle->LastAction, Handle->ReopenDelay )) { if (Timeout( Handle->LastAction, Handle->ReopenDelay )) {
Open( Handle, false ); Open( Handle, false );
@@ -2164,11 +2167,9 @@ bool CSelectableCore::Process()
} }
// Check Input buffers // Check Input buffers
if (Handle->InBuffer && (Handle->InBuffer->Len() > 0)) if (Handle->InBuffer && (Handle->InBuffer->Len() > 0)) {
{
// Check duration since last PortIn // Check duration since last PortIn
if (Timeout( Handle->InStart, Handle->InTimeout )) if (Timeout( Handle->InStart, Handle->InTimeout )) {
{
// Process Input // Process Input
ProcessInputBuffer( Handle, true ); ProcessInputBuffer( Handle, true );
@@ -2178,14 +2179,12 @@ bool CSelectableCore::Process()
} }
// Check for auto close (but not on servers) // Check for auto close (but not on servers)
if ((Handle->State == csOpen) && (Handle->Type != ctTCPserver) && (Handle->Type != ctUNIXserver) && Handle->AutoManage && !Handle->Persistent) if ((Handle->State == csOpen) && Handle->AutoManage && !Handle->Persistent && (Handle->Type != ctTCPserver) && (Handle->Type != ctUNIXserver)) {
{
// Close port after timeout // Close port after timeout
if (Timeout( Handle->LastAction, Handle->CloseTimeout )) { if (Timeout( Handle->LastAction, Handle->CloseTimeout )) {
Close( Handle, true ); Close( Handle, true );
} }
} }
Handle = Handle->Next; Handle = Handle->Next;
} }
return true; return true;
@@ -2471,3 +2470,4 @@ bool CSelectableCore::ReadSerialConfig( THandle * Handle )
return true; return true;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -37,6 +37,7 @@ const char ConnectStateName[][15] = { "None", "OpenRequest", "WaitingToOpen", "O
#define NO_FLOWCTRL 0 #define NO_FLOWCTRL 0
#define HW_FLOWCTRL 1 #define HW_FLOWCTRL 1
#define SW_FLOWCTRL 2 #define SW_FLOWCTRL 2
#define RS485_FLOWCTRL 3
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -56,16 +57,16 @@ typedef void (*FHandleCallback)( CSelectableBare * Function, THandle * Handle, E
// List of Handles for Select Object // List of Handles for Select Object
struct SSelectHandle { struct SSelectHandle {
// File Descriptor // File Descriptor
int FD; int FD = -1;
bool Read; bool Read = false;
bool Write; bool Write = false;
// Event Object // Event Object
THandle * Handle; THandle * Handle = NULL;
CSelectableBare * Function; CSelectableBare * Function = NULL;
// List // List
TSelectHandle * Next; TSelectHandle * Next = NULL;
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -73,63 +74,63 @@ struct SSelectHandle {
// List or Handles for Selectable Function Object // List or Handles for Selectable Function Object
struct SHandle { struct SHandle {
// Description // Description
char * Name; char * Name = NULL;
EConnectType Type; EConnectType Type = ctNone;
// State // State
int FD; int FD = -1;
EConnectState State; EConnectState State = csNone;
bool AutoManage; bool AutoManage = false;
bool Persistent; bool Persistent = false;
timeval LastAction; timeval LastAction = {0,0};
long ReopenDelay; // millisecs before trying to re-open socket long ReopenDelay = 1000; // millisecs before trying to re-open socket
long CloseTimeout; // millisecs of no traffic before closing socket long CloseTimeout = 1000; // millisecs of no traffic before closing socket
// Callback functions // Callback functions
FHandleCallback StateCallback[ 7 ]; FHandleCallback StateCallback[ 7 ] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
// Type specific parameters // Type specific parameters
char * Path; // Port (file)name or Exec path char * Path = NULL; // Port (file)name or Exec path
// Fork config // Fork config
pid_t ChildPID; // Forked child PID pid_t ChildPID; // Forked child PID
// Socket config // Socket config
char * HostName; // Host name or IP adddress char * HostName = NULL; // Host name or IP adddress
char * PortName; // Socket port no or protocol, e.g. "80" or "HTTP" char * PortName = NULL; // Socket port no or protocol, e.g. "80" or "HTTP"
struct addrinfo * AddressList; // List of resolved IP Addresses for host name struct addrinfo * AddressList = NULL; // List of resolved IP Addresses for host name
struct addrinfo * AddressInfo; // Current selected IP Address struct addrinfo * AddressInfo = NULL; // Current selected IP Address
bool AddressFailed; // Indicate failure to connect to address bool AddressFailed = false; // Indicate failure to connect to address
short Queue; // Max waiting connections short Queue = 2; // Max waiting connections
long ResolveDelay; // Delay before resolving hostname via DNS long ResolveDelay = 0; // Delay before resolving hostname via DNS
// Serial Port config // Serial Port config
bool SerialConfig; bool SerialConfig = false;
int InBaudrate; int InBaudrate = 0;
int OutBaudrate; int OutBaudrate = 0;
short DataBits; short DataBits = 0;
short Parity; short Parity = NO_PARITY;
short StopBits; short StopBits = 0;
short FlowCtrl; short FlowCtrl = NO_FLOWCTRL;
int DataWait; int DataWait = 0;
// Buffers // Buffers
CRollingBuffer * InBuffer; CRollingBuffer * InBuffer = NULL;
CRollingBuffer * OutBuffer; CRollingBuffer * OutBuffer = NULL;
// Input Markers // Input Markers
char * InMarker; char * InMarker = NULL;
int InMarkerLen; int InMarkerLen = 0;
// Input Timer // Input Timer
timeval InStart; timeval InStart = {0,0};
long InTimeout; // millisecs long InTimeout = 0; // millisecs
// List / Tree // List / Tree
TChannel * Channel; TChannel * Channel = NULL;
THandle * Parent; THandle * Parent = NULL;
THandle * Next; THandle * Next = NULL;
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -138,7 +139,7 @@ class CSelect
{ {
protected: protected:
// List // List
TSelectHandle * FirstHandle; TSelectHandle * FirstHandle = NULL;
// Select Variables // Select Variables
fd_set ReadTestFDS; fd_set ReadTestFDS;
@@ -148,12 +149,12 @@ protected:
fd_set WriteFDS; fd_set WriteFDS;
// Configuration // Configuration
int MaxFD; int MaxFD = 0;
timeval Timeout; timeval Timeout = {0,0};
// Output // Output
CLogCore * Log; CLogCore * Log = NULL;
EDebugLevel LogLevel; EDebugLevel LogLevel = dlNone;
public: public:
// Life Cycle // Life Cycle
@@ -185,10 +186,10 @@ class CSelectableBare : public CFunctionCore
{ {
protected: protected:
// FDs // FDs
THandle * FirstHandle; THandle * FirstHandle = NULL;
// Select interface // Select interface
CSelect * Selector; CSelect * Selector = NULL;
// Managing File Handles // Managing File Handles
bool RemoveHandle( THandle * Handle ); bool RemoveHandle( THandle * Handle );
@@ -254,6 +255,7 @@ public:
// General port parameters // General port parameters
THandle * CreateHandle( const char * HandleName, bool CreateChannel ); THandle * CreateHandle( const char * HandleName, bool CreateChannel );
virtual CDataMember * GetHandleAddress( THandle * Handle, const char * HandleRef );
bool SetCallback( THandle * Handle, EConnectState pState, FHandleCallback pCallback ); bool SetCallback( THandle * Handle, EConnectState pState, FHandleCallback pCallback );
bool SetAutoManage( THandle * Handle, bool AutoManage, bool Persistent, int ReopenDelay = 0, int CloseTimeout = 0 ); bool SetAutoManage( THandle * Handle, bool AutoManage, bool Persistent, int ReopenDelay = 0, int CloseTimeout = 0 );

View File

@@ -88,7 +88,7 @@ bool CWatchdogCore::Process()
SetStartTime( &PingTimer ); SetStartTime( &PingTimer );
} }
return false; return true;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------