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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@@ -60,6 +60,7 @@ protected:
// Function Definition
const char * Type = NULL;
char * Name = NULL;
bool WaitToTerminate = false;
// Channels
TChannel * FirstChannel = NULL;
@@ -138,6 +139,8 @@ public:
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 Process() = 0;
friend class CApplication;
};
//---------------------------------------------------------------------------

View File

@@ -15,31 +15,16 @@
//---------------------------------------------------------------------------
CJSONparse::CJSONparse()
{
SetBase( NULL );
}
//---------------------------------------------------------------------------
CJSONparse::CJSONparse( CDataMember * pDataTree )
{
// Object tree
DataTree = pDataTree;
// 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;
if (!SetBase( pDataTree ))
DataTree = NULL;
}
//---------------------------------------------------------------------------
@@ -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 )
{
// Print to screen
@@ -124,6 +121,8 @@ bool CJSONparse::WriteToHandle( const char * BasePath, const int Handle, const i
// Validate
if (!DataTree) {
Error = true;
sprintf( ErrorText, "No Data Tree set" );
return false;
}
@@ -187,11 +186,6 @@ bool CJSONparse::ReadFromFile( const char * BasePath, const char * FilePath )
int Handle = -1;
bool result = false;
// Validate
if (!DataTree) {
return false;
}
// Clear Error
Error = false;
@@ -283,7 +277,14 @@ bool CJSONparse::ReadFromBuffer( const char * BasePath )
CDataMember * BaseMember = NULL;
// 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;
}

View File

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

View File

@@ -44,9 +44,6 @@ CSelectableCore::CSelectableCore( const char * pName, const char * pType ) : CSe
{
// Quick access
Selector = Application->Selector;
// Handles
FirstHandle = NULL;
}
//---------------------------------------------------------------------------
@@ -98,6 +95,7 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
Handle = CreateHandle( HandleConfig->GetName(), false );
Handle->Channel = GetChannel( HandleConfig->GetChStr( "Channel" ) );
// Load handle specifics
Type = (char*)HandleConfig->GetChStr( "Type", "TCPclient", true );
if (!strcasecmp( Type, "Serial" ))
{
@@ -130,6 +128,8 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
FlowCtrl = HW_FLOWCTRL;
else if (!strcasecmp( FlowCtrlText, "software" ))
FlowCtrl = SW_FLOWCTRL;
else if (!strcasecmp( FlowCtrlText, "rs485" ))
FlowCtrl = RS485_FLOWCTRL;
else
FlowCtrl = NO_FLOWCTRL;
@@ -142,7 +142,7 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
}
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
} else {
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" ))
{
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
} else {
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" ))
{
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
} else {
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" ))
{
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
Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value
} else {
@@ -182,7 +182,7 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
}
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
Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value
} else {
@@ -194,7 +194,7 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
}
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
Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value
} else {
@@ -207,7 +207,7 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
}
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
Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value
} else {
@@ -253,14 +253,9 @@ bool CSelectableCore::SetSerialHandle( THandle * Handle, const char * FileName )
// Set Type
Handle->Type = ctSerial;
// Clear File Name
if (Handle->Path) {
free( Handle->Path );
}
// Set name
Handle->Path = (char*)malloc( strlen(FileName)+1 );
strcpy( Handle->Path, FileName );
// Set path
if (Handle->Path) free( Handle->Path );
Handle->Path = strdup( FileName );
// Log event
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
Handle->Type = ctLinePrinter;
// Clear File Name
if (Handle->Path) {
free( Handle->Path );
}
// Set name
Handle->Path = (char*)malloc( strlen(FileName)+1 );
strcpy( Handle->Path, FileName );
// Set Path
if (Handle->Path) free( Handle->Path );
Handle->Path = strdup( FileName );
// Log event
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
Handle->Type = ctForkPipe;
// Clear File Name
if (Handle->Path) {
free( Handle->Path );
}
// Set name
Handle->Path = (char*)malloc( strlen(ExecPath)+1 );
strcpy( Handle->Path, ExecPath );
// Set path
if (Handle->Path) free( Handle->Path );
Handle->Path = strdup( ExecPath );
// Log event
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
Handle->Path = (char*)malloc( strlen(FileName)+1 );
strcpy( Handle->Path, FileName );
Handle->Path = strdup( FileName );
Handle->Queue = Queue;
// Log event
@@ -391,11 +375,8 @@ bool CSelectableCore::SetSocketHandle( THandle * Handle, EConnectType Type, con
freeaddrinfo( Handle->AddressList );
// Set HostName & Port
Handle->HostName = (char*)malloc( strlen(HostName)+1 );
strcpy( Handle->HostName, HostName );
Handle->PortName = (char*)malloc( strlen(PortName)+1 );
strcpy( Handle->PortName, PortName );
Handle->HostName = strdup( HostName );
Handle->PortName = strdup( PortName );
Handle->AddressList = NULL;
Handle->AddressInfo = NULL;
@@ -437,6 +418,12 @@ THandle * CSelectableCore::OpenSerialPort( THandle * Handle )
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
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Serial Port opened [%s]",
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
if (Handle->Type == ctUDPremote) {
Fail = false;
@@ -1737,7 +1730,7 @@ bool CSelectableCore::Read( THandle * Handle )
// Read incoming message and address
errno = 0;
UDPbuffer = (char*)malloc( BytesWaiting+1 );
UDPbuffer = (char*)malloc( BytesWaiting+1 );
BytesRead = ReadFromUDP( Handle, (char*)UDPaddress, (char*)UDPport, UDPbuffer, BytesWaiting );
if (!errno && (Handle->Type == ctUDPserver))
@@ -1884,10 +1877,22 @@ bool CSelectableCore::Write( THandle * Handle )
{
// Write directly to handle / socket
errno = 0;
if ((Handle->Type == ctUDPclient)|| (Handle->Type == ctUDPremote)) {
if ((Handle->Type == ctUDPclient) || (Handle->Type == ctUDPremote)) {
Len = Handle->OutBuffer->Peek( &Data );
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 {
BytesWritten = Handle->OutBuffer->WriteToFD( Handle->FD );
}
@@ -2143,20 +2148,18 @@ bool CSelectableCore::Process()
{
THandle * Handle = NULL;
// Check all handles
// Process all Handles
Handle = FirstHandle;
while (Handle)
{
// Auto manage handles
if ((Handle->State == csOpenRequest))
{
if ((Handle->State == csOpenRequest)) {
// Resolve then open socket
if (Timeout( Handle->LastAction, Handle->ResolveDelay )) {
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
if (Timeout( Handle->LastAction, Handle->ReopenDelay )) {
Open( Handle, false );
@@ -2164,11 +2167,9 @@ bool CSelectableCore::Process()
}
// Check Input buffers
if (Handle->InBuffer && (Handle->InBuffer->Len() > 0))
{
if (Handle->InBuffer && (Handle->InBuffer->Len() > 0)) {
// Check duration since last PortIn
if (Timeout( Handle->InStart, Handle->InTimeout ))
{
if (Timeout( Handle->InStart, Handle->InTimeout )) {
// Process Input
ProcessInputBuffer( Handle, true );
@@ -2178,14 +2179,12 @@ bool CSelectableCore::Process()
}
// 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
if (Timeout( Handle->LastAction, Handle->CloseTimeout )) {
Close( Handle, true );
}
}
Handle = Handle->Next;
}
return true;
@@ -2471,3 +2470,4 @@ bool CSelectableCore::ReadSerialConfig( THandle * Handle )
return true;
}
//---------------------------------------------------------------------------

View File

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