From 3e40f7a86db243b217311a172346f6da26f6bd43 Mon Sep 17 00:00:00 2001 From: Charl Wentzel Date: Tue, 8 Jan 2019 08:35:21 +0200 Subject: [PATCH 1/7] Important Update: - Implement Handle Address renaming: - Restructure JSON config, with address list and rename list - SelectableCore: - Add method GetHandleAddress() - lookup renamed handle - Add init values to all struct and classes declarations - Replace malloc()/strcpy() sequences with strdup() --- ApplicationCore.cpp | 12 ++--- DeviceCore.cpp | 26 ++++------- EventBufferCore.cpp | 111 ++++++-------------------------------------- FileCore.cpp | 6 +-- FunctionCore.cpp | 12 ++--- SelectableCore.cpp | 96 ++++++++++++++++++-------------------- SelectableCore.h | 97 +++++++++++++++++++------------------- 7 files changed, 128 insertions(+), 232 deletions(-) diff --git a/ApplicationCore.cpp b/ApplicationCore.cpp index 9aaa8af..e441d53 100644 --- a/ApplicationCore.cpp +++ b/ApplicationCore.cpp @@ -104,8 +104,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 +162,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 +234,7 @@ bool CApplication::InitApplication() bool CApplication::InitFunction( CFunctionCore * Function ) { char FunctionPath[100]; - CDataMember * FunctionConfig = NULL; + CDataMember * FunctionConfig; // Validate if (!Function) @@ -274,7 +273,7 @@ bool CApplication::InitFunctions() return false; } - // Process each Channel + // Process each Function FunctionConfig = FunctionList->GetFirstChild(); while (FunctionConfig) { @@ -358,8 +357,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; diff --git a/DeviceCore.cpp b/DeviceCore.cpp index d6a8148..d1f6c35 100644 --- a/DeviceCore.cpp +++ b/DeviceCore.cpp @@ -410,8 +410,7 @@ TDevice * CDeviceCore::AddDeviceType( const char * DeviceTypeName ) else { *DeviceType = new TDevice; - (*DeviceType)->Type = (char *)malloc( strlen( DeviceTypeName )+1 ); - strcpy( (*DeviceType)->Type, DeviceTypeName ); + (*DeviceType)->Type = strdup( DeviceTypeName ); if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Added device type '%s'", ProcessName, Name, DeviceTypeName ); @@ -454,20 +453,15 @@ TDevice * CDeviceCore::AddDevice( const char * DeviceName, const char * DeviceTy else { *Device = new TDevice; - (*Device)->Name = (char *)malloc( strlen( DeviceName )+1 ); - strcpy( (*Device)->Name, DeviceName ); - - (*Device)->ID = DeviceID; + (*Device)->Name = strdup( DeviceName ); + (*Device)->ID = DeviceID; if (DeviceAddress) { - (*Device)->Address = (char *)malloc( strlen( DeviceAddress )+1 ); - strcpy( (*Device)->Address, DeviceAddress ); + (*Device)->Address = strdup( DeviceAddress ); } if (DeviceType && *DeviceType) { - (*Device)->Type = (char *)malloc( strlen( DeviceType )+1 ); - strcpy( (*Device)->Type, DeviceType ); - + (*Device)->Type = strdup( DeviceType ); (*Device)->Template = GetDeviceType( DeviceType ); } @@ -540,8 +534,7 @@ TDeviceParam * CDeviceCore::AddDeviceParam( TDevice * Device, const char * Param *Param = new TDeviceParam; // Set Name - (*Param)->Name = (char *)malloc( strlen( ParamName )+1 ); - strcpy( (*Param)->Name, ParamName ); + (*Param)->Name = strdup( ParamName ); (*Param)->DataType = DataType; (*Param)->Device = Device; @@ -683,9 +676,7 @@ TDeviceParamGroup * CDeviceCore::AddParamGroup( TDevice * Device, const char * G else { *ParamGroup = new TDeviceParamGroup; - (*ParamGroup)->Name = (char *)malloc( strlen( GroupName )+1 ); - strcpy( (*ParamGroup)->Name, GroupName ); - + (*ParamGroup)->Name = strdup( GroupName ); (*ParamGroup)->Device = Device; if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Added param group '%s/%s'", @@ -1197,8 +1188,7 @@ bool CDeviceCore::SetValue( TDeviceParam * Param, const char * Value, const int { // Ensure string is zero terminated if (Value[Len] != 0) { - TempStr = (char *)malloc( Len+1 ); - memcpy( TempStr, Value, Len ); + TempStr = strndup( Value, Len ); TempStr[Len] = 0; UseTempStr = true; } diff --git a/EventBufferCore.cpp b/EventBufferCore.cpp index ab1ad1b..3c317dc 100644 --- a/EventBufferCore.cpp +++ b/EventBufferCore.cpp @@ -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; diff --git a/FileCore.cpp b/FileCore.cpp index 2a56b62..6a96902 100644 --- a/FileCore.cpp +++ b/FileCore.cpp @@ -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 diff --git a/FunctionCore.cpp b/FunctionCore.cpp index d90682d..b8da187 100644 --- a/FunctionCore.cpp +++ b/FunctionCore.cpp @@ -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'", diff --git a/SelectableCore.cpp b/SelectableCore.cpp index 425f42a..5f36109 100644 --- a/SelectableCore.cpp +++ b/SelectableCore.cpp @@ -44,9 +44,6 @@ CSelectableCore::CSelectableCore( const char * pName, const char * pType ) : CFu { // 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" )) { @@ -142,7 +140,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 +149,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 +159,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 +168,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 +180,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 +192,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 +205,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 { @@ -243,6 +241,27 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig ) } //--------------------------------------------------------------------------- +CDataMember * CSelectableCore::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 * CSelectableCore::CreateHandle( const char * HandleName, bool CreateChannel ) { THandle ** Handle = NULL; @@ -260,8 +279,7 @@ THandle * CSelectableCore::CreateHandle( const char * HandleName, bool CreateCh // Set name if (HandleName) { - (*Handle)->Name = (char*)malloc( strlen(HandleName)+1 ); - strcpy( (*Handle)->Name, HandleName ); + (*Handle)->Name = strdup( HandleName ); } // Set File Descriptor @@ -354,14 +372,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]", @@ -399,14 +412,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]", @@ -425,14 +433,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]", @@ -459,8 +462,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 @@ -492,11 +494,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; @@ -597,8 +596,7 @@ bool CSelectableCore::SetInBuffer( THandle * Handle, int InBufSize, int InTimeou // Set Input Markers if (InMarkerLen && InMarker) { Handle->InMarkerLen = InMarkerLen; - Handle->InMarker = (char *)malloc( InMarkerLen+1 ); - memcpy( Handle->InMarker, InMarker, InMarkerLen ); + Handle->InMarker = strndup( InMarker, InMarkerLen ); Handle->InMarker[InMarkerLen] = 0; } @@ -1954,7 +1952,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)) @@ -2906,8 +2904,7 @@ bool CSelectableCore::BuildArgs( const char * ExecPath, int &Count, char * Args[ // Another quote ends parameter if (*MatchPos == '"') { Len = MatchPos-StartPos-1; // Skip end quote - Args[Count] = (char*)malloc( Len+1 ); - strncpy( Args[Count], StartPos, Len ); + Args[Count] = strndup( StartPos, Len ); Args[Count][Len] = 0; Count++; ParamStarted = false; @@ -2919,8 +2916,7 @@ bool CSelectableCore::BuildArgs( const char * ExecPath, int &Count, char * Args[ // Whitespace ends parameter if ((*MatchPos == ' ') || (*MatchPos == 0)) { Len = MatchPos-StartPos; - Args[Count] = (char*)malloc( Len+1 ); - strncpy( Args[Count], StartPos, Len ); + Args[Count] = strndup( StartPos, Len ); Args[Count][Len] = 0; Count++; ParamStarted = false; diff --git a/SelectableCore.h b/SelectableCore.h index 499226e..50ee239 100644 --- a/SelectableCore.h +++ b/SelectableCore.h @@ -55,16 +55,16 @@ typedef void (*FHandleCallback)( CSelectableCore * 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; - CSelectableCore * Function; + THandle * Handle = NULL; + CSelectableCore * Function = NULL; // List - TSelectHandle * Next; + TSelectHandle * Next = NULL; }; //--------------------------------------------------------------------------- @@ -72,63 +72,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; }; //--------------------------------------------------------------------------- @@ -137,7 +137,7 @@ class CSelect { protected: // List - TSelectHandle * FirstHandle; + TSelectHandle * FirstHandle = NULL; // Select Variables fd_set ReadTestFDS; @@ -147,12 +147,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 @@ -184,10 +184,10 @@ class CSelectableCore : public CFunctionCore { protected: // FDs - THandle * FirstHandle; + THandle * FirstHandle = NULL; // Select interface - CSelect * Selector; + CSelect * Selector = NULL; // Managing File Handles bool RemoveHandle( THandle * Handle ); @@ -278,6 +278,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 ); From 3472f506b6914c60576f7f6d8f0c05155ecb5bf2 Mon Sep 17 00:00:00 2001 From: Charl Wentzel Date: Wed, 9 Jan 2019 10:56:38 +0200 Subject: [PATCH 2/7] Major Update: - JSONparseCore: - Add initialisations values for class params - Add method AddBase() to dynamically change DataTree - Added Error messages - DeviceCore: - Implement ValueTree (JSON tree) - Node are added as devices & params are created/added - Nodes (and path) are referenced on devices & params - Node values are updated as device params are updated - Added Persistence File (not yet complete) - Updated InitDevices() & InitDeviceParams() - Split into smaller methods: CopyTemplateParam() & InitDeviceParam() - Load Device definition or Parameter maps from files - Allow loading of nested parameter map files - Load Parameter as JSON tree, generate names/path dynamically --- DeviceCore.cpp | 340 +++++++++++++++++++++++++++++++++++----------- DeviceCore.h | 18 ++- JSONparseCore.cpp | 59 ++++---- JSONparseCore.h | 30 ++-- 4 files changed, 321 insertions(+), 126 deletions(-) diff --git a/DeviceCore.cpp b/DeviceCore.cpp index d1f6c35..fc5eedc 100644 --- a/DeviceCore.cpp +++ b/DeviceCore.cpp @@ -44,7 +44,8 @@ CDeviceCore::CDeviceCore( const char * pName, const char * pType ) : CFunctionCo // Data Structures DeviceInit = true; ConfigTypes = new CDataMember(); - JSONparse = new CJSONparse( ConfigTypes ); + ValueTree = new CDataMember(); + JSONparse = new CJSONparse(); } //--------------------------------------------------------------------------- @@ -59,11 +60,14 @@ CDeviceCore::~CDeviceCore() delete JSONparse; if (ConfigTypes) delete ConfigTypes; + if (ValueTree) + delete ValueTree; } //--------------------------------------------------------------------------- bool CDeviceCore::Init( CDataMember * FunctionConfig ) { + char * PersistFile = NULL; char * ConfigName = NULL; CDataMember * PollConfig = NULL; int IntVal1; @@ -102,9 +106,20 @@ bool CDeviceCore::Init( CDataMember * FunctionConfig ) Log->Message( LogLevel, dlMedium, "%s/%s: Set polling param - Int:%d, T/O:%d, Max:%d", 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 if (DeviceInit) { - CDeviceCore::InitDevices( FunctionConfig ); + InitDevices( FunctionConfig ); + //JSONparse->SetBase( ValueTree ); + //JSONparse->WriteToScreen( NULL, 2 ); } return true; @@ -113,70 +128,164 @@ bool CDeviceCore::Init( CDataMember * FunctionConfig ) bool CDeviceCore::InitDevices( CDataMember * FunctionConfig ) { - CDataMember * DeviceData = NULL; + CDataMember * DeviceConfig = NULL; TDevice * Device = NULL; + char * Definition = NULL; char * DeviceName = NULL; int DeviceID = 0; char * DeviceAddr = NULL; char * DeviceType = NULL; + char * DataPath = NULL; // Load Device Types - DeviceData = Config->GetChFirstChild( "DeviceTypes", true ); - while (DeviceData) + DeviceConfig = Config->GetChFirstChild( "DeviceTypes", true ); + while (DeviceConfig) { - DeviceType = (char*)DeviceData->GetName(); - Device = AddDeviceType( DeviceType ); + DeviceType = (char*)DeviceConfig->GetName(); + 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 (DeviceData->isString()) { - if (JSONparse->ReadFromFile( DeviceType, DeviceData->GetStr() )) { // Contains file reference - InitDeviceParams( Device, ConfigTypes->GetChild( DeviceType ) ); + if ((Definition = (char*)DeviceConfig->GetChStr( "Definition", NULL, false ))) { + JSONparse->SetBase( ConfigTypes ); + if (JSONparse->ReadFromFile( DeviceType, Definition )) { // Contains file reference + InitDeviceParams( Device, ConfigTypes->GetChild( DeviceType ), NULL ); InitParamGroups( Device, ConfigTypes->GetChild( DeviceType ) ); - JSONparse->WriteToFile( DeviceType, DeviceData->GetStr() ); + + JSONparse->SetBase( ConfigTypes ); + JSONparse->WriteToFile( DeviceType, Definition ); } else { 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 { - if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Invalid device type config for '%s'", - ProcessName, Name, DeviceType ); + InitDeviceParams( Device, DeviceConfig, NULL ); // Contains definition + InitParamGroups( Device, DeviceConfig ); } } - DeviceData = DeviceData->GetNextPeer(); + DeviceConfig = DeviceConfig->GetNextPeer(); } // Load Actual Devices - DeviceData = Config->GetChFirstChild( "Devices", true ); - while (DeviceData) + DeviceConfig = Config->GetChFirstChild( "Devices", true ); + while (DeviceConfig) { - DeviceName = (char*)DeviceData->GetName(); - DeviceID = DeviceData->GetChInt( "ID", 0 ); - DeviceAddr = (char*)DeviceData->GetChStr( "Address", NULL ); - DeviceType = (char*)DeviceData->GetChStr( "Type", NULL ); - Device = AddDevice( DeviceName, DeviceType, DeviceID, DeviceAddr ); + DeviceName = (char*)DeviceConfig->GetName(); + if (!DeviceConfig->isObject()) { + if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Invalid device config for '%s'", + ProcessName, Name, DeviceName ); + 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) { - InitDeviceParams( Device, DeviceData ); - InitParamGroups( Device, DeviceData ); + InitDeviceParams( Device, DeviceConfig, Device->DataNode ); + InitParamGroups( Device, DeviceConfig ); } - DeviceData = DeviceData->GetNextPeer(); + DeviceConfig = DeviceConfig->GetNextPeer(); } return true; } //--------------------------------------------------------------------------- -bool CDeviceCore::InitDeviceParams( TDevice * Device, CDataMember * DeviceConfig ) +bool CDeviceCore::InitDeviceParams( TDevice * Device, CDataMember * DeviceConfig, CDataMember * ParentNode ) { - CDataMember * ParamData; + CDataMember * ParamConfig; + TDeviceParam * Template; + bool isType = (Device->Name)? false : true; + + // Copy Template Params + Template = (Device->Template)? Device->Template->FirstParam : NULL; + while (Template) { + CopyTemplateParam( Device, Template, ParentNode ); + Template = Template->Next; + } + + // Read Device Params + ParamConfig = DeviceConfig->GetChFirstChild( "Parameters", true ); + while (ParamConfig) { + InitDeviceParam( Device, ParamConfig, NULL, ((isType)? NULL : Device->DataPath), ParentNode ); + 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 ))) + { + SetParamAccess( Param, Template->Read, Template->Write ); + + 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)) { + UpdateUnsignedValue( Param, *((u_int16_t*)Template->Value), Template->Changed ); + if (Template->SetChanged) + SetUnsignedValue( Param, *((u_int16_t*)Template->Value), true ); + } + else if ((Template->DataType == dtSigned16) || (Template->DataType == dtSigned32_HL) || (Template->DataType == dtSigned32_LH)) { + UpdateSignedValue( Param, *((int16_t*)Template->Value), Template->Changed ); + if (Template->SetChanged) + SetSignedValue( Param, *((int16_t*)Template->Value), true ); + } + else if ((Template->DataType == dtFloat32_L) || (Template->DataType == dtFloat32_B)) { + UpdateFloatValue( Param, *((float*)Template->Value), Template->Changed ); + if (Template->SetChanged) + SetFloatValue( Param, *((float*)Template->Value), true ); + } + else if (Template->DataType == dtString) { + UpdateStringValue( Param, (char*)Template->Value, Template->Len, Template->Changed ); + if (Template->SetChanged) + SetStringValue( Param, (char*)Template->Value, Template->Len, true ); + } + + SetParamEvent( Param, (Template->EventChannel)? Template->EventChannel->Name : NULL, Template->EventInterval ); + } + + if (DataPath) free( DataPath ); + return true; +} +//--------------------------------------------------------------------------- + +bool CDeviceCore::InitDeviceParam( TDevice * Device, CDataMember * ParamConfig, + const char * ParentName, const char * ParentPath, CDataMember * ParentNode ) +{ + char * NodeName; + char * FullName; + char * DataPath; + CDataMember * DataNode; + CDataMember * Children; + CDataMember * ChildConfig; + CDataMember * ChildMap; + CDataMember * InitVal; TDeviceParam * Param; - TDeviceParam * Template; EDeviceDataType DataType; @@ -185,55 +294,63 @@ bool CDeviceCore::InitDeviceParams( TDevice * Device, CDataMember * DeviceConfi char * EventOut; int EventInt; - // Copy Template - Template = (Device->Template)? Device->Template->FirstParam : NULL; - while (Template) - { - if ((Param = AddDeviceParam( Device, Template->Name, Template->DataType, Template->Len ))) - { - SetParamAccess( Param, Template->Read, Template->Write ); - SetParamEvent( Param, (Template->EventChannel)? Template->EventChannel->Name : NULL, Template->EventInterval ); - - if ((Template->DataType == dtUnsigned16) || (Template->DataType == dtUnsigned32_HL) || (Template->DataType == dtUnsigned32_LH)) { - UpdateUnsignedValue( Param, *((u_int16_t*)Template->Value), Template->Changed ); - if (Template->SetChanged) - SetUnsignedValue( Param, *((u_int16_t*)Template->Value), true ); - } - else if ((Template->DataType == dtSigned16) || (Template->DataType == dtSigned32_HL) || (Template->DataType == dtSigned32_LH)) { - UpdateSignedValue( Param, *((int16_t*)Template->Value), Template->Changed ); - if (Template->SetChanged) - SetSignedValue( Param, *((int16_t*)Template->Value), true ); - } - else if ((Template->DataType == dtFloat32_L) || (Template->DataType == dtFloat32_B)) { - UpdateFloatValue( Param, *((float*)Template->Value), Template->Changed ); - if (Template->SetChanged) - SetFloatValue( Param, *((float*)Template->Value), true ); - } - else if (Template->DataType == dtString) { - UpdateStringValue( Param, (char*)Template->Value, Template->Len, Template->Changed ); - if (Template->SetChanged) - SetStringValue( Param, (char*)Template->Value, Template->Len, true ); - } - } - Template = Template->Next; + // 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 ); } - // Add Parameters - ParamData = DeviceConfig->GetChFirstChild( "Parameters", true ); - while (ParamData) - { - DataType = GetDataType((char*)ParamData->GetChStr( "Type", "Unsigned16", true )); - if ((Param = AddDeviceParam( Device, ParamData->GetName(), DataType, 1 ))) - { - Read = ParamData->GetChBool( "Read", false, true ); - Write = ParamData->GetChBool( "Write", false, true ); + // 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 (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 ); + ChildConfig = ChildConfig->GetNextPeer(); + } + } + delete ChildMap; + } + else { + // Load children + ChildConfig = Children->GetFirstChild(); + while (ChildConfig) { + InitDeviceParam( Device, ChildConfig, FullName, DataPath, DataNode ); + } + } + } + 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 ); - EventOut = (char*)ParamData->GetChStr( "EventChannel", NULL, false ); - EventInt = ParamData->GetChInt( "EventInterval", 0, false ); - SetParamEvent( Param, EventOut, EventInt ); + SetDataPath( Param, DataPath, DataNode ); - if ((InitVal = ParamData->GetChild( "InitValue", false ))) { + if ((InitVal = ParamConfig->GetChild( "InitValue", false ))) { if ((DataType == dtUnsigned16) || (DataType == dtUnsigned32_HL) || (DataType == dtUnsigned32_LH)) { UpdateUnsignedValue( Param, InitVal->GetInt(0), Read ); if (Write) @@ -255,10 +372,15 @@ bool CDeviceCore::InitDeviceParams( TDevice * Device, CDataMember * DeviceConfi SetStringValue( Param, InitVal->GetStr(""), InitVal->GetLen(), true ); } } + + EventOut = (char*)ParamConfig->GetChStr( "EventChannel", NULL, false ); + EventInt = ParamConfig->GetChInt( "EventInterval", 0, false ); + SetParamEvent( Param, EventOut, EventInt ); } - // Read + Event Out - ParamData = ParamData->GetNextPeer(); } + + if (FullName) free( FullName ); + if (DataPath) free( DataPath ); return true; } //--------------------------------------------------------------------------- @@ -394,7 +516,7 @@ bool CDeviceCore::CheckReplyTimeout() } //--------------------------------------------------------------------------- -TDevice * CDeviceCore::AddDeviceType( const char * DeviceTypeName ) +TDevice * CDeviceCore::AddDeviceType( const char * DeviceTypeName, const char * DataPath ) { TDevice ** DeviceType = GetDeviceTypePtr( DeviceTypeName ); @@ -410,7 +532,8 @@ TDevice * CDeviceCore::AddDeviceType( const char * DeviceTypeName ) else { *DeviceType = new TDevice; - (*DeviceType)->Type = strdup( DeviceTypeName ); + (*DeviceType)->Type = strdup( DeviceTypeName ); + (*DeviceType)->DataPath = strdup( DataPath ); if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Added device type '%s'", ProcessName, Name, DeviceTypeName ); @@ -419,7 +542,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; @@ -463,6 +587,18 @@ TDevice * CDeviceCore::AddDevice( const char * DeviceName, const char * DeviceTy if (DeviceType && *DeviceType) { (*Device)->Type = strdup( 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'", @@ -491,6 +627,8 @@ bool CDeviceCore::DestroyDevice( TDevice ** Device ) free( (*Device)->Address ); if ((*Device)->Type) free( (*Device)->Type ); + if ((*Device)->DataPath) + free( (*Device)->DataPath ); // Destroy parameters & groups while ((*Device)->FirstParam) { @@ -647,6 +785,8 @@ bool CDeviceCore::DestroyDeviceParam( TDeviceParam ** Param ) free( (*Param)->Value ); if ((*Param)->SetValue) free( (*Param)->SetValue ); + if ((*Param)->DataPath) + free( (*Param)->DataPath ); // Destroy Param delete *Param; @@ -772,6 +912,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 ) { if (!Param) @@ -825,6 +982,9 @@ bool CDeviceCore::UpdateUnsignedValue( TDeviceParam * Param, const u_int32_t Val // Set new value & mark change *((u_int16_t*)Param->Value) = Value; + if (Param->DataNode) + Param->DataNode->SetInt( *((u_int16_t*)Param->Value) ); + // Mark change & log event Changed = true; if (Log) { @@ -842,6 +1002,9 @@ bool CDeviceCore::UpdateUnsignedValue( TDeviceParam * Param, const u_int32_t Val // Set new value & mark change *((u_int32_t*)Param->Value) = Value; + if (Param->DataNode) + Param->DataNode->SetInt( *((u_int32_t*)Param->Value) ); + // Mark change & log event Changed = true; if (Log) { @@ -860,6 +1023,9 @@ bool CDeviceCore::UpdateUnsignedValue( TDeviceParam * Param, const u_int32_t Val // Set new value & mark change *((u_int32_t*)Param->Value) = Value; + if (Param->DataNode) + Param->DataNode->SetInt( *((u_int32_t*)Param->Value) ); + // Mark change & log event Changed = true; if (Log) { @@ -899,6 +1065,9 @@ bool CDeviceCore::UpdateSignedValue( TDeviceParam * Param, const int32_t Value, // Set new value & mark change *((int16_t*)Param->Value) = Value; + if (Param->DataNode) + Param->DataNode->SetInt( *((int16_t*)Param->Value) ); + // Mark change & log event Changed = true; if (Log) { @@ -916,6 +1085,9 @@ bool CDeviceCore::UpdateSignedValue( TDeviceParam * Param, const int32_t Value, // Set new value & mark change *((int32_t*)Param->Value) = Value; + if (Param->DataNode) + Param->DataNode->SetInt( *((int32_t*)Param->Value) ); + // Mark change & log event Changed = true; if (Log) { @@ -956,6 +1128,9 @@ bool CDeviceCore::UpdateFloatValue( TDeviceParam * Param, const float Value, boo // Set new value & mark change *((float*)Param->Value) = Value; + if (Param->DataNode) + Param->DataNode->SetFloat( *((float*)Param->Value) ); + // Mark change & log event Changed = true; if (Log) { @@ -1005,6 +1180,9 @@ bool CDeviceCore::UpdateStringValue( TDeviceParam * Param, const char * Value, c memset( &((char*)Param->Value)[Len], 0x0, (Param->Len - Len + 1) ); // Add null teriminate } + if (Param->DataNode) + Param->DataNode->SetStr( (char*)Param->Value ); + // Mark Change Changed = true; if (Log) { diff --git a/DeviceCore.h b/DeviceCore.h index b6fcdde..1253642 100644 --- a/DeviceCore.h +++ b/DeviceCore.h @@ -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; @@ -306,25 +313,30 @@ public: // Configuration virtual bool Init( 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 CopyTemplateParam( TDevice * Device, TDeviceParam * Template, CDataMember * ParentNode ); + virtual bool InitDeviceParam( TDevice * Device, CDataMember * ParamConfig, + const char * ParentName, const char * ParentPath, CDataMember * ParentNode ); virtual bool InitParamGroups( TDevice * Device, CDataMember * DeviceConfig ); // 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; diff --git a/JSONparseCore.cpp b/JSONparseCore.cpp index bca41c0..e38081d 100644 --- a/JSONparseCore.cpp +++ b/JSONparseCore.cpp @@ -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; } diff --git a/JSONparseCore.h b/JSONparseCore.h index 1938c86..e2ce0f4 100644 --- a/JSONparseCore.h +++ b/JSONparseCore.h @@ -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(); From f10750ca2d49d9448bc9e3ef94c57b449ef1e978 Mon Sep 17 00:00:00 2001 From: Charl Wentzel Date: Wed, 9 Jan 2019 15:19:06 +0200 Subject: [PATCH 3/7] Important Update: - Remove separate poll group specifications in JSON file - Implemented PollGroups per parameter or node in JSON file - Implemented copying of PollGroups from Template --- DeviceCore.cpp | 124 +++++++++++++++++++++++-------------------------- DeviceCore.h | 8 ++-- 2 files changed, 63 insertions(+), 69 deletions(-) diff --git a/DeviceCore.cpp b/DeviceCore.cpp index fc5eedc..411eafc 100644 --- a/DeviceCore.cpp +++ b/DeviceCore.cpp @@ -157,7 +157,6 @@ bool CDeviceCore::InitDevices( CDataMember * FunctionConfig ) JSONparse->SetBase( ConfigTypes ); if (JSONparse->ReadFromFile( DeviceType, Definition )) { // Contains file reference InitDeviceParams( Device, ConfigTypes->GetChild( DeviceType ), NULL ); - InitParamGroups( Device, ConfigTypes->GetChild( DeviceType ) ); JSONparse->SetBase( ConfigTypes ); JSONparse->WriteToFile( DeviceType, Definition ); @@ -169,7 +168,6 @@ bool CDeviceCore::InitDevices( CDataMember * FunctionConfig ) } else { InitDeviceParams( Device, DeviceConfig, NULL ); // Contains definition - InitParamGroups( Device, DeviceConfig ); } } DeviceConfig = DeviceConfig->GetNextPeer(); @@ -195,7 +193,6 @@ bool CDeviceCore::InitDevices( CDataMember * FunctionConfig ) if (Device) { InitDeviceParams( Device, DeviceConfig, Device->DataNode ); - InitParamGroups( Device, DeviceConfig ); } DeviceConfig = DeviceConfig->GetNextPeer(); } @@ -215,11 +212,12 @@ bool CDeviceCore::InitDeviceParams( TDevice * Device, CDataMember * DeviceConfi 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 ); + InitDeviceParam( Device, ParamConfig, NULL, ((isType)? NULL : Device->DataPath), ParentNode, NULL ); ParamConfig = ParamConfig->GetNextPeer(); } @@ -273,8 +271,36 @@ bool CDeviceCore::CopyTemplateParam( TDevice * Device, TDeviceParam * Template, } //--------------------------------------------------------------------------- -bool CDeviceCore::InitDeviceParam( TDevice * Device, CDataMember * ParamConfig, - const char * ParentName, const char * ParentPath, CDataMember * ParentNode ) +bool CDeviceCore::CopyTemplateParamGroups( TDevice * Device ) +{ + TDeviceParamGroup * TemplateGroup; + 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; @@ -289,8 +315,12 @@ bool CDeviceCore::InitDeviceParam( TDevice * Device, CDataMember * ParamConfig, EDeviceDataType DataType; + char * ParamGroupName; + SDeviceParamGroup * ParamGroup; + bool Read; bool Write; + char * EventOut; int EventInt; @@ -314,6 +344,12 @@ bool CDeviceCore::InitDeviceParam( TDevice * Device, CDataMember * ParamConfig, if ((Children = ParamConfig->GetChild( "Children", false ))) { // Data Branch + if ((ParamGroupName = (char*)ParamConfig->GetChStr( "PollGroup", NULL, false ))) { + ParamGroup = AddParamGroup( Device, ParamGroupName ); + } else { + ParamGroup = ParentParamGroup; + } + if (Children->isString()) { // Load from file ChildMap = new CDataMember(); @@ -325,7 +361,7 @@ bool CDeviceCore::InitDeviceParam( TDevice * Device, CDataMember * ParamConfig, else { ChildConfig = ChildMap->GetFirstChild(); while (ChildConfig) { - InitDeviceParam( Device, ChildConfig, FullName, DataPath, DataNode ); + InitDeviceParam( Device, ChildConfig, FullName, DataPath, DataNode, ParamGroup ); ChildConfig = ChildConfig->GetNextPeer(); } } @@ -335,7 +371,8 @@ bool CDeviceCore::InitDeviceParam( TDevice * Device, CDataMember * ParamConfig, // Load children ChildConfig = Children->GetFirstChild(); while (ChildConfig) { - InitDeviceParam( Device, ChildConfig, FullName, DataPath, DataNode ); + InitDeviceParam( Device, ChildConfig, FullName, DataPath, DataNode, ParamGroup ); + ChildConfig = ChildConfig->GetNextPeer(); } } } @@ -373,6 +410,14 @@ bool CDeviceCore::InitDeviceParam( TDevice * Device, CDataMember * ParamConfig, } } + if ((ParamGroupName = (char*)ParamConfig->GetChStr( "PollGroup", NULL, false ))) { + ParamGroup = AddParamGroup( Device, ParamGroupName ); + } else { + ParamGroup = ParentParamGroup; + } + if (ParamGroup) + AddParamItem( ParamGroup, Param ); + EventOut = (char*)ParamConfig->GetChStr( "EventChannel", NULL, false ); EventInt = ParamConfig->GetChInt( "EventInterval", 0, false ); SetParamEvent( Param, EventOut, EventInt ); @@ -385,50 +430,6 @@ bool CDeviceCore::InitDeviceParam( TDevice * Device, CDataMember * ParamConfig, } //--------------------------------------------------------------------------- -bool CDeviceCore::InitParamGroups( TDevice * Device, CDataMember * DeviceConfig ) -{ - CDataMember * GroupData; - CDataMember * ItemData; - TDeviceParamGroup * Group; - TDeviceParamGroup * GroupTemplate; - TDeviceParamItem * ItemTemplate; - - // Copy Template - GroupTemplate = (Device->Template)? Device->Template->FirstParamGroup : NULL; - while (GroupTemplate) - { - 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(); - } - - return true; -} -//--------------------------------------------------------------------------- - bool CDeviceCore::SetPollParam( int pPollInterval ) { PollInterval = pPollInterval; @@ -857,27 +858,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 ); - TDeviceParam * Param = NULL; + TDeviceParamItem ** Item; - if (!Item) { + if (!Param || !(Item = GetParamItemPtr( Group, Param->Name ))) { // Invalid group/param 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; } else if (*Item) { // Item already exists if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Param Group item '%s/%s' already exists", - ProcessName, Name, Group->Name, ParamName ); - } - 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 ); + ProcessName, Name, Group->Name, Param->Name ); } else { *Item = new TDeviceParamItem; @@ -891,7 +885,7 @@ TDeviceParamItem * CDeviceCore::AddParamItem( TDeviceParamGroup * Group, const c 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), - Group->Name, ParamName ); + Group->Name, Param->Name ); } return *Item; } diff --git a/DeviceCore.h b/DeviceCore.h index 1253642..f4bad96 100644 --- a/DeviceCore.h +++ b/DeviceCore.h @@ -315,9 +315,9 @@ public: virtual bool InitDevices( CDataMember * FunctionConfig ); virtual bool InitDeviceParams( TDevice * Device, CDataMember * DeviceConfig, CDataMember * ParentNode ); virtual bool CopyTemplateParam( TDevice * Device, TDeviceParam * Template, CDataMember * ParentNode ); - virtual bool InitDeviceParam( TDevice * Device, CDataMember * ParamConfig, - const char * ParentName, const char * ParentPath, CDataMember * ParentNode ); - virtual bool InitParamGroups( TDevice * Device, CDataMember * DeviceConfig ); + 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 ); @@ -355,7 +355,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; From b679da9c29e5337d161f335cdb597900025a2942 Mon Sep 17 00:00:00 2001 From: Charl Wentzel Date: Wed, 9 Jan 2019 15:48:37 +0200 Subject: [PATCH 4/7] Important Update: - Renamed JSON parameter: PollGroup -> ParamGroup --- DeviceCore.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DeviceCore.cpp b/DeviceCore.cpp index 411eafc..a54fc9c 100644 --- a/DeviceCore.cpp +++ b/DeviceCore.cpp @@ -344,7 +344,7 @@ bool CDeviceCore::InitDeviceParam( TDevice * Device, CDataMember * ParamConfig, if ((Children = ParamConfig->GetChild( "Children", false ))) { // Data Branch - if ((ParamGroupName = (char*)ParamConfig->GetChStr( "PollGroup", NULL, false ))) { + if ((ParamGroupName = (char*)ParamConfig->GetChStr( "ParamGroup", NULL, false ))) { ParamGroup = AddParamGroup( Device, ParamGroupName ); } else { ParamGroup = ParentParamGroup; @@ -410,7 +410,7 @@ bool CDeviceCore::InitDeviceParam( TDevice * Device, CDataMember * ParamConfig, } } - if ((ParamGroupName = (char*)ParamConfig->GetChStr( "PollGroup", NULL, false ))) { + if ((ParamGroupName = (char*)ParamConfig->GetChStr( "ParamGroup", NULL, false ))) { ParamGroup = AddParamGroup( Device, ParamGroupName ); } else { ParamGroup = ParentParamGroup; From 49294ab6b5e8434707ef2947c42b73d23aebe079 Mon Sep 17 00:00:00 2001 From: Charl Wentzel Date: Thu, 10 Jan 2019 11:46:41 +0200 Subject: [PATCH 5/7] Important Update: - Update Command port: - Simplified error handling - Provide error reply - Added method GetNextParamGroup() --- DeviceCore.cpp | 255 ++++++++++++++++++++++++------------------------- DeviceCore.h | 5 + 2 files changed, 129 insertions(+), 131 deletions(-) diff --git a/DeviceCore.cpp b/DeviceCore.cpp index a54fc9c..3515a6f 100644 --- a/DeviceCore.cpp +++ b/DeviceCore.cpp @@ -1404,8 +1404,10 @@ bool CDeviceCore::SetValue( TDeviceParam * Param, const char * Value, const int bool CDeviceCore::GetValue( TDeviceParam * Param, char * Value, int &Len ) { // Validate - if (!Param || !Value) + if (!Param || !Value) { + Value[0] = 0; return false; + } // Check if return value longer than actual value switch (Param->DataType) @@ -1448,6 +1450,7 @@ bool CDeviceCore::GetValue( TDeviceParam * Param, char * Value, int &Len ) break; default : + Value[0] = 0; break; } return true; @@ -1512,8 +1515,13 @@ bool CDeviceCore::GetCmdParam( const char * Start, char * Param, char ** NextPar int ParamLen; // Get length of param - if ((NextDelimeter = strchr( (char*)Start, ',' ))) { - ParamLen = NextDelimeter - Start; + if (!Start || !*Start) { + Param[0] = 0; + NextParam = NULL; + return false; + } + else if ((NextDelimeter = strchr( (char*)Start, ',' ))) { + ParamLen = NextDelimeter - Start; *NextParam = NextDelimeter + 1; } else { @@ -1537,162 +1545,147 @@ bool CDeviceCore::GetCmdParam( const char * Start, char * Param, char ** NextPar int CDeviceCore::HandleCommand( const char *ChannelName, const char * Data, const int MaxLen ) { int Len; - char ParamName[50]; + char Value[50]; char * NextParam = NULL; TDevice * Device = NULL; - TDeviceParam * Param = NULL; + TDeviceParam * Param = NULL; char OutputStr[250]; + bool Error = false; // Show accepted input Log->Output( LogLevel, dlHigh, loNormal, Data, MaxLen, "%s/%s: Channel '%s' - IN:", ProcessName, Name, ChannelName ); // Get command command - GetCmdParam( Data, ParamName, &NextParam ); - if (!strcasecmp( "get", ParamName )) + GetCmdParam( Data, Value, &NextParam ); + if (!strcasecmp( "get", Value )) { - // Check for additional parameters - if (!NextParam) { - // No Parameters - Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Missing 'get' parameters", - ProcessName, Name, ChannelName ); - return MaxLen; + // Validate parameters + if (!GetCmdParam( NextParam, Value, &NextParam)) { + strcpy( OutputStr, "- Missing device name" ); + Error = true; + } + else if (!(Device = GetDeviceByName( Value ))) { + strcpy( OutputStr, "- Device not found"); + Error = true; + } + else if (!GetCmdParam( NextParam, Value, &NextParam )) { + strcpy( OutputStr, "- Missing parameter name" ); + Error = true; + } + else if (!(Param = GetDeviceParam( Device, Value ))) { + strcpy( OutputStr, "- Device parameter not found"); + Error = true; + } + else if (NextParam) { + strcpy( OutputStr, "- Too many parameters"); + Error = true; + } + else { + sprintf( OutputStr, "> %s,%s = ", Device->Name, Param->Name ); + Len = MaxLen - strlen(OutputStr) - 1; + + if (!GetValue( (TDeviceParam*)Param, &OutputStr[ strlen(OutputStr) ], Len )) { + strcpy( OutputStr, "- Error getting parameter"); + Error = true; + } + else { + strcat( OutputStr, "\n" ); + Output( ChannelName, OutputStr, strlen(OutputStr) ); + } } - // Get device name - GetCmdParam( NextParam, ParamName, &NextParam ); - if (!(Device = GetDeviceByName( ParamName ))) { - // Unknown Parameters - Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown 'get' Device: '%s'", - ProcessName, Name, ChannelName, ParamName ); - return MaxLen; + // 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) ); } - - // Get parameter name - GetCmdParam( NextParam, ParamName, &NextParam ); - 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; - } - - // Check for additional parameters - if (NextParam) { - // Unused Parameters - Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unnecessary 'get' parameters", - ProcessName, Name, ChannelName ); - return MaxLen; - } - - // Build reply - sprintf( OutputStr, "get,%s,", Param->Name ); - Len = MaxLen - strlen(OutputStr); - - // Insert value - if (!GetValue( (TDeviceParam*)Param, &OutputStr[ strlen(OutputStr) ], Len )) - return false; - - // Send reply - strcat( OutputStr, "\n" ); - Output( ChannelName, OutputStr, strlen(OutputStr) ); - return true; } - else if (!strcasecmp( "set", ParamName )) + else if (!strcasecmp( "set", Value )) { - // Check for additional parameters - if (!NextParam) { - // No Parameters - Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Missing 'set' parameters", - ProcessName, Name, ChannelName ); - return MaxLen; + // Validate parameters + if (!GetCmdParam( NextParam, Value, &NextParam)) { + strcpy( OutputStr, "- Missing device name" ); + Error = true; + } + else if (!(Device = GetDeviceByName( Value ))) { + strcpy( OutputStr, "- Device not found"); + Error = true; + } + else if (!GetCmdParam( NextParam, Value, &NextParam )) { + strcpy( OutputStr, "- Missing parameter name" ); + Error = true; + } + else if (!(Param = GetDeviceParam( Device, Value ))) { + strcpy( OutputStr, "- Device parameter not found"); + Error = true; + } + else if (!GetCmdParam( NextParam, Value, &NextParam )) { + strcpy( OutputStr, "- Missing set value"); + Error = true; + } + else if (NextParam) { + strcpy( OutputStr, "- Too many parameters"); + Error = true; + } + else { + if (!SetValue( Param, Value, strlen(Value), true )) { + strcpy( OutputStr, "- Error seting parameter"); + Error = true; + } + else { + sprintf( OutputStr, "> set %s,%s = %s\n", Device->Name, Param->Name, Value ); + Output( ChannelName, OutputStr ); + } } - // Get Device name - GetCmdParam( NextParam, ParamName, &NextParam ); - if (!(Device = GetDeviceByName( ParamName ))) { - // Unknown Parameters - Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown 'set' Device: '%s'", - ProcessName, Name, ChannelName, ParamName ); - return MaxLen; + // 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) ); } - - // Get parameter name - GetCmdParam( NextParam, ParamName, &NextParam ); - 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; - } - - // Get parameter value - GetCmdParam( NextParam, ParamName, &NextParam ); - if (strlen(ParamName) == 0) { - // No Parameters - Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - No 'set' value parameter", - ProcessName, Name, ChannelName ); - return MaxLen; - } - - // Check for additional parameters - if (NextParam) { - // Unused Parameters - Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unnecessary 'set' parameters", - ProcessName, Name, ChannelName ); - return MaxLen; - } - - // Set value - Len = MaxLen; - if (!SetValue( Param, ParamName, Len, true )) - return false; - - // Build & send reply - sprintf( OutputStr, "set,%s,%s\n", Param->Name, ParamName ); - Output( ChannelName, OutputStr ); - return true; } - else if (!strcasecmp( "status", ParamName )) + else if (!strcasecmp( "status", Value )) { - // Check for additional parameters - if (!NextParam) { - // No Parameters - Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Missing 'status' parameters", - ProcessName, Name, ChannelName ); - return MaxLen; + // Validate parameters + if (!GetCmdParam( NextParam, Value, &NextParam)) { + strcpy( OutputStr, "- Missing device name" ); + Error = true; + } + else if (!(Device = GetDeviceByName( Value ))) { + strcpy( OutputStr, "- Device not found"); + Error = true; + } + else if (NextParam) { + strcpy( OutputStr, "- Too many parameters"); + Error = true; + } + else { + sprintf( OutputStr, "> %s - %s\n", Device->Name, ((Device->Online)? "online" : "offline") ); + Output( ChannelName, OutputStr ); } - // Get Device name - GetCmdParam( NextParam, ParamName, &NextParam ); - if (!(Device = GetDeviceByName( ParamName ))) { - // Unknown Parameters - Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown 'status' Device: '%s'", - ProcessName, Name, ChannelName, ParamName ); - return MaxLen; + // 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) ); } - - // Check for additional parameters - if (NextParam) { - // Unused Parameters - Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unnecessary 'status' parameters", - ProcessName, Name, ChannelName ); - return MaxLen; - } - - // Build & send reply - sprintf( OutputStr, "status,%s,%d\n", Device->Name, Device->Online ); - Output( ChannelName, OutputStr ); - return true; } else { // Unrecognised command - Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unrecognized command: '%s'", - ProcessName, Name, ChannelName, ParamName ); - return MaxLen; + strcpy( OutputStr, "- Unknown command"); + Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s', %s%s", + ProcessName, Name, ChannelName, Value, OutputStr ); + strcat( OutputStr, " (comma separated values)\n" ); + Output( ChannelName, OutputStr, strlen(OutputStr) ); } - return MaxLen; } //--------------------------------------------------------------------------- diff --git a/DeviceCore.h b/DeviceCore.h index f4bad96..2cd7347 100644 --- a/DeviceCore.h +++ b/DeviceCore.h @@ -231,6 +231,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; From 36269097862c81753e4c9ddd012c04ce2ca17360 Mon Sep 17 00:00:00 2001 From: Charl Wentzel Date: Mon, 4 Mar 2019 16:42:29 +0200 Subject: [PATCH 6/7] Important Update: - Added SendEnable (vir RTS pin) for TTL/RS485 converter - Bug fix: Check for Handle->InTimeout before force output --- SelectableCore.cpp | 32 +++++++++++++++++++++++++++++--- SelectableCore.h | 1 + 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/SelectableCore.cpp b/SelectableCore.cpp index 5f36109..f7dd274 100644 --- a/SelectableCore.cpp +++ b/SelectableCore.cpp @@ -128,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; @@ -652,6 +654,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 ); @@ -1748,6 +1756,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; @@ -2099,10 +2113,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 ); } @@ -2163,7 +2189,7 @@ bool CSelectableCore::ProcessInputBuffer( THandle * Handle, bool Force ) } // Check if forced processed - if (Force || !Handle->InMarkerLen) + if (Force || (!Handle->InMarkerLen && !Handle->InTimeout)) { // Show Packet Len = Handle->InBuffer->Peek( &Data ); @@ -2180,7 +2206,7 @@ bool CSelectableCore::ProcessInputBuffer( THandle * Handle, bool Force ) // Clear processed bytes from buffer Handle->InBuffer->Clear( Len ); } - else + else if (Handle->InMarkerLen) { // Search for end of packet marker while (Handle->InBuffer->FindStr( Handle->InMarker, Handle->InMarkerLen, Pos )) diff --git a/SelectableCore.h b/SelectableCore.h index 50ee239..cc97344 100644 --- a/SelectableCore.h +++ b/SelectableCore.h @@ -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 //--------------------------------------------------------------------------- From 889df6c7ded98d68571bbf555653e8a1bb57f98e Mon Sep 17 00:00:00 2001 From: Charl Wentzel Date: Sat, 9 Mar 2019 20:41:25 +0200 Subject: [PATCH 7/7] Important Update: - DeviceCore: - Added PollCycle variable (not used here) - WatchdogCore: - Return "true" on in Process() - SelectableCore: - Minor update (code compacted) - Application/Function: - Added CApplication as friend of CFunction - Added param WaitToTerminate on Function - Application Run() only exists if all (WaitToTerminate) functions has terminated cleanly. --- ApplicationCore.cpp | 22 +++++++++++++--------- DeviceCore.cpp | 1 + DeviceCore.h | 5 +++-- FunctionCore.h | 3 +++ SelectableCore.cpp | 18 ++++++------------ WatchdogCore.cpp | 2 +- 6 files changed, 27 insertions(+), 24 deletions(-) diff --git a/ApplicationCore.cpp b/ApplicationCore.cpp index e441d53..3f6a1b4 100644 --- a/ApplicationCore.cpp +++ b/ApplicationCore.cpp @@ -17,6 +17,7 @@ //--------------------------------------------------------------------------- // Global Vars +extern bool Terminate; extern char * ProcessName; //--------------------------------------------------------------------------- @@ -405,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 @@ -416,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; } //--------------------------------------------------------------------------- diff --git a/DeviceCore.cpp b/DeviceCore.cpp index 3515a6f..5beb5f9 100644 --- a/DeviceCore.cpp +++ b/DeviceCore.cpp @@ -30,6 +30,7 @@ extern CApplication * Application; CDeviceCore::CDeviceCore( const char * pName, const char * pType ) : CFunctionCore( pName, pType ) { // Polling + PollCycle = 0; PollStep = 0; PollInterval = 250; SetStartTime( &PollWait ); diff --git a/DeviceCore.h b/DeviceCore.h index 2cd7347..9f43f95 100644 --- a/DeviceCore.h +++ b/DeviceCore.h @@ -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 //--------------------------------------------------------------------------- @@ -138,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 diff --git a/FunctionCore.h b/FunctionCore.h index 37c75f0..b04266a 100644 --- a/FunctionCore.h +++ b/FunctionCore.h @@ -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; }; //--------------------------------------------------------------------------- diff --git a/SelectableCore.cpp b/SelectableCore.cpp index f7dd274..2214ca5 100644 --- a/SelectableCore.cpp +++ b/SelectableCore.cpp @@ -2564,20 +2564,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 ); @@ -2585,11 +2583,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 ); @@ -2599,14 +2595,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; diff --git a/WatchdogCore.cpp b/WatchdogCore.cpp index af11199..cebd535 100644 --- a/WatchdogCore.cpp +++ b/WatchdogCore.cpp @@ -88,7 +88,7 @@ bool CWatchdogCore::Process() SetStartTime( &PingTimer ); } - return false; + return true; } //---------------------------------------------------------------------------