From 3f568364da461ab3221c3e11f6756908d7ef2556 Mon Sep 17 00:00:00 2001 From: Charl Wentzel Date: Tue, 11 Dec 2018 19:55:44 +0200 Subject: [PATCH] Important Update: - DataTreeCore: - Rename enum EDataType -> EJsonDataType - DeviceCore: - Rename enum EMBDataType -> EDeviceDataType - Add method GetNextTypeDevice() method - Bug fix: Add Type Name: 0 -> "none" - Added permanent Event Channel to TDevice - Add param Type to TDevice - Removed UpdateInterval/Timeout params & methods from TDevice - Separated DeviceInit() method from Init() - Add param DeviceInit to force/avoid DeviceInit() in Init() - Renamed and restructured SetUpdate() & SetParamScan() methods to: SetParamAccess() & SetParamEvent() - Converted DestroyDevice() and DestroyDeviceParam() to inline methods - Moved methods GetCmdParam() and HandleCommand() from CModbusInterface - Renamed TDeviceParam field: UpdateInterval/Timeout -> EventInterval/Timeout - Renamed TDeviceParam field: Scan -> Read - Added TDeviceParam field: Write --- DataTreeCore.cpp | 6 +- DataTreeCore.h | 12 +- DeviceCore.cpp | 395 +++++++++++++++++++++++++++++++++++++---------- DeviceCore.h | 103 +++++++----- 4 files changed, 393 insertions(+), 123 deletions(-) diff --git a/DataTreeCore.cpp b/DataTreeCore.cpp index b92790d..8f4c7e5 100644 --- a/DataTreeCore.cpp +++ b/DataTreeCore.cpp @@ -353,7 +353,7 @@ bool CDataMember::DeleteCh( const char * Path ) } //--------------------------------------------------------------------------- -bool CDataMember::SetValuePtr( EDataType pType, const char * pValue, int pLen ) +bool CDataMember::SetValuePtr( EJsonDataType pType, const char * pValue, int pLen ) { Clear(); Type = pType; @@ -367,7 +367,7 @@ bool CDataMember::SetValuePtr( EDataType pType, const char * pValue, int pLen ) } //--------------------------------------------------------------------------- -bool CDataMember::SetValue( EDataType pType, const char * pValue, int pLen ) +bool CDataMember::SetValue( EJsonDataType pType, const char * pValue, int pLen ) { // Clear & Update Type Clear(); @@ -511,7 +511,7 @@ const char * CDataMember::GetChName( const char * Path ) } //--------------------------------------------------------------------------- -EDataType CDataMember::GetChType( const char * Path ) +EJsonDataType CDataMember::GetChType( const char * Path ) { CDataMember * Member; diff --git a/DataTreeCore.h b/DataTreeCore.h index afae4f7..a930d24 100644 --- a/DataTreeCore.h +++ b/DataTreeCore.h @@ -16,7 +16,7 @@ //--------------------------------------------------------------------------- -typedef enum { jtNull = 0, jtBool = 1, jtInt = 2, jtFloat = 3, jtString = 4, jtArray = 5, jtObject = 6 } EDataType; +typedef enum { jtNull = 0, jtBool = 1, jtInt = 2, jtFloat = 3, jtString = 4, jtArray = 5, jtObject = 6 } EJsonDataType; //--------------------------------------------------------------------------- @@ -25,7 +25,7 @@ class CDataMember { char * Name; unsigned short NameLen; - EDataType Type; + EJsonDataType Type; char * Value; unsigned short Len; @@ -41,8 +41,8 @@ class CDataMember CDataMember * CreateChild( const char * Name, const int Len = -1 ); // Set Member value - bool SetValue( EDataType Type, const char * Value = NULL, int Len = -1 ); - bool SetValuePtr( EDataType pType, const char * pValue, int pLen = -1 ); + bool SetValue( EJsonDataType Type, const char * Value = NULL, int Len = -1 ); + bool SetValuePtr( EJsonDataType pType, const char * pValue, int pLen = -1 ); public: CDataMember( const char * pName = NULL, const int pLen = -1 ); @@ -57,8 +57,8 @@ public: /* Check Type */ - EDataType GetType() { return Type; }; - EDataType GetChType( const char * Path ); + EJsonDataType GetType() { return Type; }; + EJsonDataType GetChType( const char * Path ); inline bool isNull() { return (Type == jtNull); }; inline bool isBool() { return (Type == jtBool); }; diff --git a/DeviceCore.cpp b/DeviceCore.cpp index caf9daa..af52957 100644 --- a/DeviceCore.cpp +++ b/DeviceCore.cpp @@ -36,6 +36,7 @@ CDeviceCore::CDeviceCore( const char * pName, const char * pType ) : CFunctionCo // Standard channels DeviceChannel = NULL; CmdChannel = NULL; + EventChannel = NULL; // Polling PollStep = 0; @@ -48,11 +49,9 @@ CDeviceCore::CDeviceCore( const char * pName, const char * pType ) : CFunctionCo PollRetry = 0; MaxRetries = 3; - // Update Timer - SetUpdate( 0 ); - // Data Structures - Config = NULL; + Config = NULL; + DeviceInit = true; } //--------------------------------------------------------------------------- @@ -75,6 +74,14 @@ bool CDeviceCore::Init( CDataMember * FunctionConfig ) if (!CFunctionCore::Init( FunctionConfig )) return false; + // Add Channels + if (!(CmdChannel = GetChannel( "Command" ))) + CmdChannel = AddChannel( "Command", true, true ); + if (!(DeviceChannel = GetChannel( "Device" ))) + DeviceChannel = AddChannel( "Device", true, true ); + if (!(DeviceChannel = GetChannel( "Event" ))) + DeviceChannel = AddChannel( "Event", true, true ); + // Get configuration if ((Config = FunctionConfig->GetChild( "Config", true )) && Config->isString()) { ConfigName = (char*)FunctionConfig->GetChStr( "Config" ); @@ -93,12 +100,85 @@ bool CDeviceCore::Init( CDataMember * FunctionConfig ) IntVal2 = PollConfig->GetChInt( "MaxRetries", 3, true ); SetReplyParam( IntVal1, IntVal2 ); - IntVal1 = PollConfig->GetChInt( "UpdateInterval", 1000, true ); - SetUpdate( IntVal1 ); - Log->Message( LogLevel, dlMedium, "%s/%s: Set Polling param - Int:%d, TO:%d, Max:%d, Up:%d", - ProcessName, Name, PollInterval, ReplyTimeout, MaxRetries, UpdateInterval ); + ProcessName, Name, PollInterval, ReplyTimeout, MaxRetries ); + // Update Devices -- may want to do it from derived class intead + if (DeviceInit) { + InitDevices( FunctionConfig ); + } + + return true; +} +//--------------------------------------------------------------------------- + +bool CDeviceCore::InitDevices( CDataMember * FunctionConfig ) +{ + CDataMember * DeviceData; + CDataMember * ParamData; + CDataMember * InitVal; + TDevice * Device; + TDeviceParam * Param; + + EDeviceDataType DataType; + + bool Read; + bool Write; + char * EventOut; + int EventInt; + + // Add Devices + DeviceData = Config->GetChFirstChild( "Devices", true ); + while (DeviceData) + { + // Add device + Device = AddDevice( DeviceData->GetName() ); + Param = NULL; + + // Add Parameters + ParamData = DeviceData->GetChFirstChild( "Parameters", true ); + while (ParamData) + { + DataType = GetDataType((char*)ParamData->GetChStr( "Type", "Unsigned16", true )); + if (!(Param = AddDeviceParam( Device, ParamData->GetName(), DataType, 1 ))) + continue; + + Read = ParamData->GetChBool( "Read", false, true ); + Write = ParamData->GetChBool( "Write", false, true ); + SetParamAccess( Param, Read, Write ); + + if ((InitVal = ParamData->GetChild( "InitValue", false ))) { + if (InitVal->isInt() && ((DataType == dtUnsigned16) || (DataType == dtUnsigned32))) { + UpdateUnsignedValue( Param, InitVal->GetInt(0), Read ); + if (Write) + SetUnsignedValue( Param, InitVal->GetInt(0), true ); + } + else if (InitVal->isInt() && ((DataType == dtSigned16) || (DataType == dtSigned32))) { + UpdateSignedValue( Param, InitVal->GetInt(0), Read ); + if (Write) + SetSignedValue( Param, InitVal->GetInt(0), true ); + } + else if (InitVal->isFloat() && (DataType == dtFloat32)) { + UpdateFloatValue( Param, InitVal->GetFloat(0), Read ); + if (Write) + SetFloatValue( Param, InitVal->GetFloat(0), true ); + } + else if (InitVal->isString() && (DataType == dtString)) { + UpdateStringValue( Param, InitVal->GetStr(""), InitVal->GetLen(), Read ); + if (Write) + SetStringValue( Param, InitVal->GetStr(""), InitVal->GetLen(), true ); + } + } + + EventOut = (char*)ParamData->GetChStr( "EventChannel", NULL, false ); + EventInt = ParamData->GetChInt( "EventInterval", 0, false ); + SetParamEvent( Param, EventOut, EventInt ); + + // Read + Event Out + ParamData = ParamData->GetNextPeer(); + } + DeviceData = DeviceData->GetNextPeer(); + } return true; } //--------------------------------------------------------------------------- @@ -118,15 +198,6 @@ bool CDeviceCore::SetReplyParam( int pReplyTimeout, int pMaxRetries ) } //--------------------------------------------------------------------------- -// Generate events -bool CDeviceCore::SetUpdate( int pUpdateInterval ) -{ - UpdateInterval = pUpdateInterval; - SetStartTime( &UpdateTimeout ); - return true; -} -//--------------------------------------------------------------------------- - bool CDeviceCore::DeviceOnline( TDevice * Device, bool Online ) { // Validate @@ -192,54 +263,43 @@ bool CDeviceCore::CheckReplyTimeout( int TimeoutPollStep ) } //--------------------------------------------------------------------------- -TDevice * CDeviceCore::AddDevice( const char * DeviceName ) +TDevice * CDeviceCore::AddDevice( const char * DeviceName, const char * Type ) { - // Get register or end of list TDevice ** Device = &FirstDevice; + + if (!DeviceName || !*DeviceName) return NULL; + while (*Device && strcmp( DeviceName, (*Device)->Name )) Device = &((*Device)->Next); // Create if not found - if (!*Device) { - // Create register + if (!*Device) + { *Device = (TDevice*)malloc( sizeof(TDevice) ); memset( *Device, 0x0, sizeof(TDevice) ); - // Set Name (*Device)->Name = (char *)malloc( strlen( DeviceName )+1 ); strcpy( (*Device)->Name, DeviceName ); + + if (Type && *Type) { + (*Device)->Type = (char *)malloc( strlen( Type )+1 ); + strcpy( (*Device)->Type, Type ); + } } // Report creation - if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Device added - '%s'", - ProcessName, Name, DeviceName ); + if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Device added - '%s' (%s)", + ProcessName, Name, DeviceName, (Type)? Type : "no type" ); return *Device; } //--------------------------------------------------------------------------- -bool CDeviceCore::DestroyDevice( const char * DeviceName ) -{ - TDevice ** Device = NULL; - - // Find device - if (!(Device = GetDevicePtr(DeviceName))) - return false; - - // Destroy Device - if (!DestroyDevice( Device )) - return false; - - // Device destroyed - return true; -} -//--------------------------------------------------------------------------- - bool CDeviceCore::DestroyDevice( TDevice ** Device ) { TDevice * NextDevice = NULL; - // Validate param + // Validate Device if (!Device || !*Device) return false; @@ -249,13 +309,15 @@ bool CDeviceCore::DestroyDevice( TDevice ** Device ) // Destroy Device structure if ((*Device)->Name) free( (*Device)->Name ); + if ((*Device)->Type) + free( (*Device)->Type ); // Destroy paramters while ((*Device)->FirstParam) { DestroyDeviceParam( &((*Device)->FirstParam) ); } - // Destory Device + // Destroy Device free( *Device ); // Remove from list @@ -266,7 +328,7 @@ bool CDeviceCore::DestroyDevice( TDevice ** Device ) } //--------------------------------------------------------------------------- -TDeviceParam * CDeviceCore::AddDeviceParam( TDevice * Device, const char * ParamName, EMBDataType DataType, int ParamLen ) +TDeviceParam * CDeviceCore::AddDeviceParam( TDevice * Device, const char * ParamName, EDeviceDataType DataType, int ParamLen ) { // Get register or end of list TDeviceParam ** Param = &Device->FirstParam; @@ -375,23 +437,6 @@ TDeviceParam * CDeviceCore::AddDeviceParam( TDevice * Device, const char * Param } //--------------------------------------------------------------------------- -bool CDeviceCore::DestroyDeviceParam( TDevice * Device, const char * ParamName ) -{ - TDeviceParam ** Param = NULL; - - // Find param - if (!(Param = GetDeviceParamPtr( Device, ParamName ))) - return false; - - // Destroy Param - if (!DestroyDeviceParam( Param )) - return false; - - // Parameter destroyed - return true; -} -//--------------------------------------------------------------------------- - bool CDeviceCore::DestroyDeviceParam( TDeviceParam ** Param ) { TDeviceParam * NextParam = NULL; @@ -894,22 +939,27 @@ bool CDeviceCore::CompareParamString( const char * ParamValue, const int ParamLe } //--------------------------------------------------------------------------- -bool CDeviceCore::SetParamScan( TDeviceParam * Param, bool Scan, const char * ChannelName, long pUpdateInterval ) +bool CDeviceCore::SetParamAccess( TDeviceParam * Param, bool Read, bool Write ) { - // Validate if (!Param) return false; - // Set scan parameters - Param->Scan = Scan; - Param->EventChannel = GetChannel( ChannelName ); + Param->Read = Read; + Param->Write = Write; + return true; +} +//--------------------------------------------------------------------------- - // Configure Update timer - if (pUpdateInterval) { - Param->UpdateInterval = pUpdateInterval; - SetStartTime( &(Param->UpdateTimeout) ); +bool CDeviceCore::SetParamEvent( TDeviceParam * Param, const char * ChannelName, long pEventInterval ) +{ + if (!Param) + return false; + + Param->EventChannel = GetChannel( ChannelName ); + if (pEventInterval) { + Param->EventInterval = pEventInterval; + SetStartTime( &(Param->EventTimeout) ); } - return true; } //--------------------------------------------------------------------------- @@ -923,10 +973,8 @@ bool CDeviceCore::TimedParamEvents() Device = FirstDevice; while (Device) { - // Loop through all scan parameters - while ((Param = GetNextScanParam( Device, Param ))) - { - // Generate timed events + // Loop through all Read parameters + while ((Param = GetNextReadParam( Device, Param ))) { EventOutput( Param, false ); } Device = Device->Next; @@ -935,6 +983,197 @@ bool CDeviceCore::TimedParamEvents() } //--------------------------------------------------------------------------- +bool CDeviceCore::GetCmdParam( const char * Start, char * Param, char ** NextParam ) +{ + char * NextDelimeter; + int ParamLen; + + // Get length of param + if ((NextDelimeter = strchr( (char*)Start, ',' ))) { + ParamLen = NextDelimeter - Start; + *NextParam = NextDelimeter + 1; + } + else { + // remove \r\n if necessary + ParamLen = strlen( Start ); + if (Start[ParamLen-1] == '\n') + ParamLen--; + if (Start[ParamLen-1] == '\r') + ParamLen--; + *NextParam = NULL; + } + + // Copy param + strncpy( Param, Start, ParamLen ); + Param[ParamLen] = 0; + + return true; +} +//--------------------------------------------------------------------------- + +int CDeviceCore::HandleCommand( const char *ChannelName, const char * Data, const int MaxLen ) +{ + int Len; + char ParamName[50]; + char * NextParam = NULL; + TDevice * Device = NULL; + TDeviceParam * Param = NULL; + char OutputStr[250]; + + // 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 )) + { + // Check for additional parameters + if (!NextParam) { + // No Parameters + Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Missing parameters for 'Get'", + ProcessName, Name, ChannelName ); + return MaxLen; + } + + // Get device name + GetCmdParam( NextParam, ParamName, &NextParam ); + if (!(Device = GetDevice( ParamName ))) { + // Unknown Parameters + Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown Device: '%s'", + ProcessName, Name, ChannelName, ParamName ); + return MaxLen; + } + + // Get parameter name + GetCmdParam( NextParam, ParamName, &NextParam ); + if (!(Param = GetDeviceParam( Device, ParamName ))) { + // Unknown Parameters + Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown 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 parameters for 'Get'", + 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 )) + { + // Check for additional parameters + if (!NextParam) { + // No Parameters + Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Missing parameters for 'Set'", + ProcessName, Name, ChannelName ); + return MaxLen; + } + + // Get Device name + GetCmdParam( NextParam, ParamName, &NextParam ); + if (!(Device = GetDevice( ParamName ))) { + // Unknown Parameters + Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown Device: '%s'", + ProcessName, Name, ChannelName, ParamName ); + return MaxLen; + } + + // Get parameter name + GetCmdParam( NextParam, ParamName, &NextParam ); + if (!(Param = GetDeviceParam( Device, ParamName ))) { + // Unknown Parameters + Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown 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 value parameter for 'Set'", + ProcessName, Name, ChannelName ); + return MaxLen; + } + + // Check for additional parameters + if (NextParam) { + // Unused Parameters + Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unnecessary parameters for 'Get'", + 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 )) + { + // Check for additional parameters + if (!NextParam) { + // No Parameters + Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Missing parameters for 'Set'", + ProcessName, Name, ChannelName ); + return MaxLen; + } + + // Get Device name + GetCmdParam( NextParam, ParamName, &NextParam ); + if (!(Device = GetDevice( ParamName ))) { + // Unknown Parameters + Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown Device: '%s'", + ProcessName, Name, ChannelName, ParamName ); + return MaxLen; + } + + // Check for additional parameters + if (NextParam) { + // Unused Parameters + Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unnecessary parameters for 'Status'", + 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; + } + + return MaxLen; +} +//--------------------------------------------------------------------------- + // Generate Event output bool CDeviceCore::EventOutput( TDeviceParam * Param, bool Force ) { @@ -944,7 +1183,7 @@ bool CDeviceCore::EventOutput( TDeviceParam * Param, bool Force ) // Check Timer or force if (Force || - (Param->UpdateInterval && Timeout( Param->UpdateTimeout, Param->UpdateInterval )) ) + (Param->EventInterval && Timeout( Param->EventTimeout, Param->EventInterval )) ) { // Post event char Message[200]; @@ -980,8 +1219,8 @@ bool CDeviceCore::EventOutput( TDeviceParam * Param, bool Force ) Output( Param->EventChannel, Message, strlen(Message) ); // Reset timer - if (Param->UpdateInterval) { - SetStartTime( &(Param->UpdateTimeout) ); + if (Param->EventInterval) { + SetStartTime( &(Param->EventTimeout) ); } } return true; diff --git a/DeviceCore.h b/DeviceCore.h index b162ff8..85f817d 100644 --- a/DeviceCore.h +++ b/DeviceCore.h @@ -17,11 +17,11 @@ //--------------------------------------------------------------------------- // Enumerated types -typedef enum { dtNone = 0, dtUnsigned16 = 1, dtSigned16 = 2, dtUnsigned32 = 3, dtSigned32 = 4, dtFloat32 = 5, dtString = 6 } EMBDataType; +typedef enum { dtNone = 0, dtUnsigned16 = 1, dtSigned16 = 2, dtUnsigned32 = 3, dtSigned32 = 4, dtFloat32 = 5, dtString = 6 } EDeviceDataType; // Constants const char DataTypeCount = 6; -const char DataTypeName[][20] = { "Unsigned16", "Signed16", "Unsigned32", "Signed32", "Float32", "String" }; +const char DataTypeName[][20] = { "None", "Unsigned16", "Signed16", "Unsigned32", "Signed32", "Float32", "String" }; //--------------------------------------------------------------------------- @@ -31,32 +31,44 @@ typedef struct SDeviceParam TDeviceParam; // Devices with are polled struct SDevice { + // Device definition char * Name; + char * Type; + + // Device status bool Online; + // Device parameters TDeviceParam * FirstParam; + // Device peer list TDevice * Next; }; // Data parameters of devices struct SDeviceParam { + // Parameter definition char * Name; - EMBDataType DataType; + EDeviceDataType DataType; - bool Scan; + // Polling/Event parameters + bool Read; TChannel * EventChannel; - long UpdateInterval; - timeval UpdateTimeout; + long EventInterval; + timeval EventTimeout; + // Last value received from device void * Value; int Len; bool Changed; + // Value to on device + bool Write; void * SetValue; int SetLen; bool SetChanged; + // Parameter peer list TDeviceParam * Next; }; @@ -73,10 +85,7 @@ class CDeviceCore : public CFunctionCore protected: // Configuration CDataMember * Config; - - // Update - int UpdateInterval; - timeval UpdateTimeout; + bool DeviceInit; // Parameters TDevice * FirstDevice; @@ -85,6 +94,7 @@ protected: // Standard channels TChannel * DeviceChannel; TChannel * CmdChannel; + TChannel * EventChannel; // Poll int PollStep; // Position in polling sequence @@ -115,8 +125,14 @@ protected: Device = &((*Device)->Next); return Device; } - inline TDevice * GetNextOnlineDevice( TDevice * LastDevice ) { - TDevice * Device = LastDevice; + inline TDevice * GetNextTypeDevice( const char * Type, TDevice * PrevDevice = NULL ) { + TDevice * Device = (PrevDevice)? PrevDevice->Next : FirstDevice; + while (Device && ((!Type && Device->Type) || (Type && (!Device->Type || !strcasecmp( Type, Device->Type ))))) + Device = Device->Next; + return Device; + } + inline TDevice * GetNextOnlineDevice( TDevice * PrevDevice = NULL ) { + TDevice * Device = (PrevDevice)? PrevDevice->Next : FirstDevice; while (Device && !Device->Online) Device = Device->Next; return Device; @@ -126,24 +142,24 @@ protected: bool DestroyDeviceParam( TDeviceParam ** Param ); // Find Params - inline TDeviceParam * GetDeviceParam( TDevice * Device, const char * Name ) { - if (!Device) return NULL; + inline TDeviceParam * GetDeviceParam( TDevice * Device, const char * pName ) { + if (!Device || !pName) return NULL; TDeviceParam * Param = Device->FirstParam; - while (Param && strcasecmp( Param->Name, Name )) + while (Param && strcasecmp( Param->Name, pName )) Param = Param->Next; return Param; } - inline TDeviceParam ** GetDeviceParamPtr( TDevice * Device, const char * Name ) { - if (!Device) return NULL; - TDeviceParam ** Param = &Device->FirstParam; - while (*Param && strcasecmp( (*Param)->Name, Name )) + inline TDeviceParam ** GetDeviceParamPtr( TDevice * Device, const char * pName ) { + if (!Device || !pName) return NULL; + TDeviceParam ** Param = &(Device->FirstParam); + while (*Param && strcasecmp( (*Param)->Name, pName )) Param = &((*Param)->Next); return Param; } - inline TDeviceParam * GetNextScanParam( TDevice * Device, TDeviceParam * LastParam = NULL ) { + inline TDeviceParam * GetNextReadParam( TDevice * Device, TDeviceParam * LastParam = NULL ) { if (!Device) return NULL; TDeviceParam * Param = (LastParam)? LastParam->Next : Device->FirstParam; - while (Param && (!Param->Scan)) + while (Param && (!Param->Read)) Param = Param->Next; return Param; } @@ -163,11 +179,11 @@ protected: } // Tools - inline EMBDataType GetDataType( const char * TypeName ) { + inline EDeviceDataType GetDataType( const char * TypeName ) { int Type; for (Type = 0; Type < DataTypeCount; Type++) if (!strcasecmp( TypeName, DataTypeName[Type])) break; - return (Type == DataTypeCount)? dtNone : (EMBDataType)Type; + return (Type == DataTypeCount)? dtNone : (EDeviceDataType)Type; } bool CompareParamString( const char * ParamValue, const int ParamLen, const char * Value, const int Len ); @@ -189,39 +205,54 @@ public: virtual ~CDeviceCore(); // Configuration - bool Init( CDataMember * FunctionConfig ); + virtual bool Init( CDataMember * FunctionConfig ); + virtual bool InitDevices( CDataMember * FunctionConfig ); - // Generate events + // Polling parameters bool SetPollParam( int pPollInterval ); bool SetReplyParam( int pReplyTimeout, int pMaxRetries ); - bool SetUpdate( int pUpdateInterval ); - bool SetParamScan( TDeviceParam * Param, bool Scan, const char * ChannelName, long pUpdateInterval ); + + bool SetParamAccess( TDeviceParam * Param, bool Read, bool Write ); + bool SetParamEvent( TDeviceParam * Param, const char * ChannelName, long pEventInterval ); // Manage Devices - TDevice * AddDevice( const char * DeviceName ); - bool DestroyDevice( const char * DeviceName ); + TDevice * AddDevice( const char * DeviceName, const char * Type = NULL ); + inline bool DestroyDevice( const char * DeviceName ) { + TDevice ** Device = GetDevicePtr(DeviceName); + return (Device)? DestroyDevice( Device ) : false; + } // Manage Params - TDeviceParam * AddDeviceParam( TDevice * Device, const char * ParamName, EMBDataType DataType, int ParamLen = 1 ); - bool DestroyDeviceParam( TDevice * Device, const char * ParamName ); + TDeviceParam * AddDeviceParam( TDevice * Device, const char * ParamName, EDeviceDataType DataType, int ParamLen = 1 ); + inline bool DestroyDeviceParam( TDevice * Device, const char * ParamName ) { + TDeviceParam ** Param = GetDeviceParamPtr( Device, ParamName ); + return (Param)? DestroyDeviceParam( Param ) : false; + }; // Update/Init Param values bool UpdateUnsignedValue( TDeviceParam * Param, const u_int32_t Value, bool Init ); bool UpdateSignedValue( TDeviceParam * Param, const int32_t Value, bool Init ); bool UpdateFloatValue( TDeviceParam * Param, const float Value, bool Init ); bool UpdateStringValue( TDeviceParam * Param, const char * Value, const int Len, bool Init ); - bool UpdateStringValue( TDeviceParam * Param, const char * Value, bool Init ) - { return UpdateStringValue( Param, Value, strlen(Value), Init ); }; + inline bool UpdateStringValue( TDeviceParam * Param, const char * Value, bool Init ) { + return UpdateStringValue( Param, Value, strlen(Value), Init ); + }; // Change Param Update instruction bool SetUnsignedValue( TDeviceParam * Param, const u_int32_t Value, bool Force ); bool SetSignedValue( TDeviceParam * Param, const int32_t Value, bool Force ); bool SetFloatValue( TDeviceParam * Param, const float Value, bool Force ); bool SetStringValue( TDeviceParam * Param, const char * Value, const int Len, bool Force ); - bool SetStringValue( TDeviceParam * Param, const char * Value, bool Force ) - { return SetStringValue( Param, Value, strlen(Value), Force ); }; + inline bool SetStringValue( TDeviceParam * Param, const char * Value, bool Force ) { + return SetStringValue( Param, Value, strlen(Value), Force ); + }; - // Text Interfaces + + // Handle Interface Commands + bool GetCmdParam( const char * Start, char * Param, char ** NextParam ); + int HandleCommand( const char *ChannelName, const char * Data, const int MaxLen ); + + // Command Text Interfaces bool SetValue( TDeviceParam * Param, const char * Value, const int Len, bool Force ); bool GetValue( TDeviceParam * Param, char * Value, int &Len ); };