diff --git a/CMakeLists.txt b/CMakeLists.txt index 90e69a5..c413d7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,3 @@ PROJECT(lib_redAcore) -ADD_LIBRARY(redAcore TimingCore.cpp LogCore.cpp SignalCore.cpp BufferCore.cpp FunctionCore.cpp FileCore.cpp SelectCore.cpp SelectableCore.cpp) +ADD_LIBRARY(redAcore TimingCore.cpp LogCore.cpp SignalCore.cpp BufferCore.cpp FunctionCore.cpp DeviceCore.cpp FileCore.cpp SelectCore.cpp SelectableCore.cpp) diff --git a/DeviceCore.cpp b/DeviceCore.cpp new file mode 100644 index 0000000..d354ea1 --- /dev/null +++ b/DeviceCore.cpp @@ -0,0 +1,805 @@ +/* + * FunctionCore.cpp + * + * Created on: 18 May 2016 + * Author: wentzelc + */ + +//--------------------------------------------------------------------------- + +// Standard C/C++ Libraries +#include +#include +#include +#include +#include +#include + +// redA Libraries +#include "DeviceCore.h" +#include "FunctionCore.h" +#include "TimingCore.h" +#include "LogCore.h" + +//--------------------------------------------------------------------------- + +CDeviceCore::CDeviceCore( const char * Name, CLogCore * pLog, EDebugLevel DebugLevel, int pOutputDisplay ) : + CFunctionCore( Name, pLog, DebugLevel, pOutputDisplay ) +{ + // Clear Parameters + FirstDevice = NULL; + ActiveDevice = NULL; + + // Standard channels + DeviceChannel = NULL; + CmdChannel = NULL; + + // Polling + PollStep = 0; + PollInterval = 250; + SetStartTime( &PollWait ); + + WaitingForReply = false; + ReplyTimeout = 200; + + PollRetry = 0; + MaxRetries = 3; + + // Update Timer + SetUpdate( 0 ); +} +//--------------------------------------------------------------------------- + +CDeviceCore::~CDeviceCore() +{ + // Destroy Params + while (FirstDevice) + DestroyDevice( &FirstDevice ); +} +//--------------------------------------------------------------------------- + +bool CDeviceCore::SetPollParam( int pPollInterval ) +{ + PollInterval = pPollInterval; + return true; +} +//--------------------------------------------------------------------------- + +bool CDeviceCore::SetReplyParam( int pReplyTimeout, int pMaxRetries ) +{ + ReplyTimeout = pReplyTimeout; + MaxRetries = pMaxRetries; + return true; +} +//--------------------------------------------------------------------------- + +// Generate events +bool CDeviceCore::SetUpdate( int pUpdateInterval ) +{ + UpdateInterval = pUpdateInterval; + SetStartTime( &UpdateTimeout ); + return true; +} +//--------------------------------------------------------------------------- + +bool CDeviceCore::DeviceOnline( TDevice * Device, bool Online ) +{ + // Validate + if (!Device) + return false; + + // Check if change of state + if (Device->Online == Online) + return true; + + // Log Event + Device->Online = Online; + Log->Message( DebugLevel, dlHigh, "%s: Device '%s' %s", Name, Device->Name, ((Online)? "online" : "offline") ); + return true; +} +//--------------------------------------------------------------------------- + +void CDeviceCore::SetWaitForReply() +{ + // Start timer + SetStartTime( &PollWait ); + + // Set flag + WaitingForReply = true; +} +//--------------------------------------------------------------------------- + +bool CDeviceCore::CheckReplyTimeout( int TimeoutPollStep ) +{ + // Check for Reply timeout + if (WaitingForReply && Timeout( PollWait, ReplyTimeout )) + { + // Increment retries + PollRetry++; + + // Handle No Reply / Retry + if (PollRetry < MaxRetries) { + // Log Event + Log->Message( DebugLevel, dlHigh, "%s: Channel '%s' - %s timeout, retry [%d]", Name, DeviceChannel->Name, ActiveDevice->Name, PollRetry ); + } + else { + // Log Event + Log->Message( DebugLevel, dlHigh, "%s: Channel '%s' - %s timeout, max [%d]", Name, DeviceChannel->Name, ActiveDevice->Name, PollRetry ); + + // Set Device Offline + DeviceOnline( ActiveDevice, false ); + PollStep = TimeoutPollStep; + } + + // Reset flag - retry + WaitingForReply = false; + return true; + } + else + { + // Reset retries + PollRetry = 0; + return false; + } +} +//--------------------------------------------------------------------------- + +TDevice * CDeviceCore::AddDevice( const char * DeviceName ) +{ + // Get register or end of list + TDevice ** Device = &FirstDevice; + while (*Device && strcmp( DeviceName, (*Device)->Name )) + Device = &((*Device)->Next); + + // Create if not found + if (!*Device) { + // Create register + *Device = (TDevice*)malloc( sizeof(TDevice) ); + memset( *Device, 0x0, sizeof(TDevice) ); + + // Set Name + (*Device)->Name = (char *)malloc( strlen( DeviceName )+1 ); + strcpy( (*Device)->Name, DeviceName ); + } + + // Report creation + Log->Message( DebugLevel, dlLow, "%s: Device added - '%s'", Name, DeviceName ); + + 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 + if (!Device || !*Device) + return false; + + // Save reference to next Device + NextDevice = (*Device)->Next; + + // Destroy Device structure + if ((*Device)->Name) + free( (*Device)->Name ); + + // Destroy paramters + while ((*Device)->FirstParam) { + DestroyDeviceParam( &((*Device)->FirstParam) ); + } + + // Destory Device + free( *Device ); + + // Remove from list + *Device = NextDevice; + + // Device successfully destroyed + return true; +} +//--------------------------------------------------------------------------- + +TDeviceParam * CDeviceCore::AddDeviceParam( TDevice * Device, const char * ParamName, EDataType DataType, int ParamLen ) +{ + // Get register or end of list + TDeviceParam ** Param = &Device->FirstParam; + while (*Param && strcmp( ParamName, (*Param)->Name )) + Param = &((*Param)->Next); + + // Create if not found + if (!*Param) { + // Create register + *Param = (TDeviceParam*)malloc( sizeof(TDeviceParam) ); + memset( *Param, 0x0, sizeof(TDeviceParam) ); + + // Set Name + (*Param)->Name = (char *)malloc( strlen( ParamName )+1 ); + strcpy( (*Param)->Name, ParamName ); + (*Param)->DataType = DataType; + + // Init values + switch (DataType) + { + case dtUnsigned16 : + // Create Value pointer + (*Param)->Value = (u_int16_t*)malloc( sizeof(u_int16_t) ); + *((u_int16_t*)(*Param)->Value) = 0; + (*Param)->Len = sizeof(u_int16_t); + + // Create Set Value pointer + (*Param)->SetValue = (u_int16_t*)malloc( sizeof(u_int16_t) ); + *((u_int16_t*)(*Param)->SetValue) = 0; + (*Param)->SetLen = sizeof(u_int16_t); + break; + + case dtSigned16 : + // Create Value pointer + (*Param)->Value = (int16_t*)malloc( sizeof(int16_t) ); + *((int16_t*)(*Param)->Value) = 0; + (*Param)->Len = sizeof(int16_t); + + // Create Set Value pointer + (*Param)->SetValue = (int16_t*)malloc( sizeof(int16_t) ); + *((int16_t*)(*Param)->SetValue) = 0; + (*Param)->SetLen = sizeof(int16_t); + break; + + case dtUnsigned32 : + // Create Value pointer + (*Param)->Value = (u_int32_t*)malloc( sizeof(u_int32_t) ); + *((u_int32_t*)(*Param)->Value) = 0; + (*Param)->Len = sizeof(u_int32_t); + + // Create Set Value pointer + (*Param)->SetValue = (u_int32_t*)malloc( sizeof(u_int32_t) ); + *((u_int32_t*)(*Param)->SetValue) = 0; + (*Param)->SetLen = sizeof(u_int32_t); + break; + + case dtSigned32 : + // Create Value pointer + (*Param)->Value = (int32_t*)malloc( sizeof(int32_t) ); + *((int32_t*)(*Param)->Value) = 0; + (*Param)->Len = sizeof(int32_t); + + // Create Set Value pointer + (*Param)->SetValue = (int32_t*)malloc( sizeof(int32_t) ); + *((int32_t*)(*Param)->SetValue) = 0; + (*Param)->SetLen = sizeof(int32_t); + break; + + case dtFloat32 : + // Create Value pointer + (*Param)->Value = (float*)malloc( sizeof(float) ); + *((float*)(*Param)->Value) = 0.0; + (*Param)->Len = sizeof(float); + + // Create Set Value pointer + (*Param)->SetValue = (float*)malloc( sizeof(float) ); + *((float*)(*Param)->SetValue) = 0.0; + (*Param)->SetLen = sizeof(float); + break; + + case dtString : + // Create Value pointer + (*Param)->Len = ParamLen; + (*Param)->Value = (char*)malloc( ParamLen + 1 ); + memset( (*Param)->Value, 0x0, (*Param)->Len+1 ); + + // Create Set Value pointer + (*Param)->SetLen = ParamLen; + (*Param)->SetValue = (char*)malloc( ParamLen + 1 ); + memset( (*Param)->SetValue, 0x0, (*Param)->SetLen+1 ); + break; + } + } + + // Mark as updated + (*Param)->Changed = true; + + // Report creation + Log->Message( DebugLevel, dlLow, "%s: Param added - '%s' (%s)", Name, ParamName, DataTypeName[DataType] ); + + return *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; + + // Validate param + if (!Param || !*Param) + return false; + + // Save reference to next Param + NextParam = (*Param)->Next; + + // Destroy Param structure + if ((*Param)->Name) + free( (*Param)->Name ); + if ((*Param)->Value) + free( (*Param)->Value ); + if ((*Param)->SetValue) + free( (*Param)->SetValue ); + + // Destroy Param + free( *Param ); + + // Remove from list + *Param = NextParam; + + // Parameter successfully destroyed + return true; +} +//--------------------------------------------------------------------------- + +bool CDeviceCore::UpdateUnsignedValue( TDeviceParam * Param, const u_int32_t Value, bool Init ) +{ + bool Changed = false; + + // Validate + if (!Param) + return false; + + switch (Param->DataType) + { + case dtUnsigned16 : + if (Init || (*((u_int16_t*)Param->Value) != Value)) + { + // Set new value & mark change + *((u_int16_t*)Param->Value) = Value; + + // Mark change & log event + Changed = true; + Log->Message( DebugLevel, dlLow, "%s: '%s' %s - %u", Name, Param->Name, ((Init)? "initialised" : "changed"), *((u_int16_t*)Param->Value) ); + } + break; + + case dtUnsigned32 : + if (Init || (*((u_int32_t*)Param->Value) != Value)) + { + // Set new value & mark change + *((u_int32_t*)Param->Value) = Value; + + // Mark change & log event + Changed = true; + Log->Message( DebugLevel, dlLow, "%s: '%s' %s - %u", Name, Param->Name, ((Init)? "initialised" : "changed"), *((u_int32_t*)Param->Value) ); + } + break; + + case dtFloat32 : // Special case, where float value is stored in Integer memory (e.g. modbus register) + if (Init || (*((u_int32_t*)Param->Value) != Value)) + { + // Set new value & mark change + *((u_int32_t*)Param->Value) = Value; + + // Mark change & log event + Changed = true; + Log->Message( DebugLevel, dlLow, "%s: '%s' %s - %f", Name, Param->Name, ((Init)? "initialised" : "changed"), *((float*)Param->Value) ); + } + break; + + default : + // Invalid Data Type + return false; + } + // Generate Channel Event + if (Changed) { + Param->Changed = true; + EventOutput( Param, Changed ); + } + return Changed; +} +//--------------------------------------------------------------------------- + +bool CDeviceCore::UpdateSignedValue( TDeviceParam * Param, const int32_t Value, bool Init ) +{ + bool Changed = false; + + // Validate + if (!Param) + return false; + + switch (Param->DataType) + { + case dtSigned16 : + if (Init || (*((int16_t*)Param->Value) != Value)) + { + // Set new value & mark change + *((int16_t*)Param->Value) = Value; + + // Mark change & log event + Changed = true; + Log->Message( DebugLevel, dlLow, "%s: '%s' %s - %u", Name, Param->Name, ((Init)? "initialised" : "changed"), *((int16_t*)Param->Value) ); + } + break; + + case dtSigned32 : + if (Init || (*((int32_t*)Param->Value) != Value)) + { + // Set new value & mark change + *((int32_t*)Param->Value) = Value; + + // Mark change & log event + Changed = true; + Log->Message( DebugLevel, dlLow, "%s: '%s' %s - %u", Name, Param->Name, ((Init)? "initialised" : "changed"), *((int32_t*)Param->Value) ); + } + break; + + default : + // Invalid Data Type + return false; + } + // Generate Channel Event + if (Changed) { + Param->Changed = true; + EventOutput( Param, Changed ); + } + return Changed; +} +//--------------------------------------------------------------------------- + +bool CDeviceCore::UpdateFloatValue( TDeviceParam * Param, const float Value, bool Init ) +{ + bool Changed = false; + + // Validate + if (!Param) + return false; + + switch (Param->DataType) + { + case dtFloat32 : + if (Init || (*((float*)Param->Value) != Value)) + { + // Set new value & mark change + *((float*)Param->Value) = Value; + + // Mark change & log event + Changed = true; + Log->Message( DebugLevel, dlLow, "%s: '%s' %s - %f", Name, Param->Name, ((Init)? "initialised" : "changed"), *((float*)Param->Value) ); + } + break; + + default : + // Invalid Data Type + return false; + } + // Generate Channel Event + if (Changed) { + Param->Changed = true; + EventOutput( Param, Changed ); + } + return Changed; +} +//--------------------------------------------------------------------------- + +bool CDeviceCore::UpdateStringValue( TDeviceParam * Param, const char * Value, const int Len, bool Init ) +{ + bool Changed = false; + + // Validate + if (!Param || (Param->DataType != dtString)) + return false; + + // Update register + if (Init || !CompareParamString( (char*)Param->Value, Param->Len, Value, Len)) + { + if (Len >= Param->Len) { + // Copy full register length (ignore additional bytes) + memcpy( Param->Value, Value, Param->Len ); + ((char*)Param->Value)[ Param->Len ] = 0; // null terminate + } + else { + // Copy new value + memcpy( Param->Value, Value, Len ); + // Zero pad remaining + memset( &((char*)Param->Value)[Len], 0x0, (Param->Len - Len + 1) ); // Add null teriminate + } + + // Mark Change + Changed = true; + Log->Message( DebugLevel, dlLow, "%s: '%s' %s - %s", Name, Param->Name, ((Init)? "initialised" : "changed"), (char*)Param->Value ); + } + // Generate Channel Event + if (Changed) { + Param->Changed = true; + EventOutput( Param, Changed ); + } + return Changed; +} +//--------------------------------------------------------------------------- + +bool CDeviceCore::SetUnsignedValue( TDeviceParam * Param, const u_int32_t Value, bool Force ) +{ + // Validate + if (!Param) + return false; + + switch (Param->DataType) + { + case dtUnsigned16 : + if (Force || (*((u_int16_t*)Param->SetValue) != Value)) + { + // Set new value + *((u_int16_t*)Param->SetValue) = Value; + + // Mark change + Param->SetChanged = true; + } + break; + + case dtUnsigned32 : + if (Force || (*((u_int32_t*)Param->SetValue) != Value)) + { + // Set new value + *((u_int32_t*)Param->SetValue) = Value; + + // Mark change + Param->SetChanged = true; + } + break; + + default : + // Invalid data + return false; + } + + return true; +} +//--------------------------------------------------------------------------- + +bool CDeviceCore::SetSignedValue( TDeviceParam * Param, const int32_t Value, bool Force ) +{ + // Validate + if (!Param) + return false; + + switch (Param->DataType) + { + case dtSigned16 : + if (Force || (*((int16_t*)Param->SetValue) != Value)) + { + // Set new value + *((int16_t*)Param->SetValue) = Value; + + // Mark change + Param->SetChanged = true; + } + break; + + case dtSigned32 : + if (Force || (*((int32_t*)Param->SetValue) != Value)) + { + // Set new value + *((int32_t*)Param->SetValue) = Value; + + // Mark change + Param->SetChanged = true; + } + break; + + default : + // Invalid data + return false; + } + + return true; +} +//--------------------------------------------------------------------------- + +bool CDeviceCore::SetFloatValue( TDeviceParam * Param, const float Value, bool Force ) +{ + // Validate + if (!Param) + return false; + + switch (Param->DataType) + { + case dtFloat32 : + if (Force || (*((float*)Param->SetValue) != Value)) + { + // Set new value + *((float*)Param->SetValue) = Value; + + // Mark change + Param->SetChanged = true; + } + break; + + default : + // Invalid data + return false; + } + + return true; +} +//--------------------------------------------------------------------------- + +bool CDeviceCore::SetStringValue( TDeviceParam * Param, const char * Value, const int Len, bool Force ) +{ + // Validate + if (!Param || (Param->DataType != dtString) || (Len > Param->Len)) + return false; + + // Update register + if (Force || !CompareParamString( (char*)Param->Value, Param->Len, Value, Len)) + { + if (Len >= Param->SetLen) { + // Copy full register length (ignore additional bytes) + memcpy( Param->SetValue, Value, Param->SetLen ); + ((char*)Param->SetValue)[ Param->SetLen ] = 0; // null terminate + } + else { + // Copy new value + memcpy( Param->SetValue, Value, Len ); + // Zero pad remaining + memset( &((char*)Param->SetValue)[Len], 0x0, (Param->SetLen - Len + 1) ); // null terminate + } + + // Mark Change + Param->SetChanged = true; + } + return true; +} +//--------------------------------------------------------------------------- + +bool CDeviceCore::CompareParamString( const char * ParamValue, const int ParamLen, const char * Value, const int Len ) +{ + bool Match = true; + char * Pos = NULL; + + // Compare Value against current value + if (Len >= ParamLen) { + // Compare full register length (ignore additional bytes) + if (memcmp( Value, ParamValue, ParamLen)) { + Match = false; + } + } + else { + // Compare length of new value only + if (memcmp( ParamValue, Value, Len)) { + Match = false; + } + // Remaining bytes must be null + else { + for (Pos = (char*)ParamValue; Pos < (char*)ParamValue + ParamLen; Pos++) { + if (*Pos != 0) { + Match = false; + break; + } + } + } + } + + // Return result + return Match; +} +//--------------------------------------------------------------------------- + +bool CDeviceCore::SetParamScan( TDeviceParam * Param, bool Scan, const char * ChannelName, long pUpdateInterval ) +{ + // Validate + if (!Param) + return false; + + // Set scan parameters + Param->Scan = Scan; + Param->EventChannel = GetChannel( ChannelName ); + + // Configure Update timer + if (pUpdateInterval) { + Param->UpdateInterval = pUpdateInterval; + SetStartTime( &(Param->UpdateTimeout) ); + } + + return true; +} +//--------------------------------------------------------------------------- + +bool CDeviceCore::TimedParamEvents() +{ + TDevice * Device = NULL; + TDeviceParam * Param = NULL; + + // Loop through all devices + Device = FirstDevice; + while (Device) + { + // Loop through all scan parameters + while ((Param = GetNextScanParam( Device, Param ))) + { + // Generate timed events + EventOutput( Param, false ); + } + Device = Device->Next; + } + return true; +} +//--------------------------------------------------------------------------- + +// Generate Event output +bool CDeviceCore::EventOutput( TDeviceParam * Param, bool Force ) +{ + // Validate + if (!Param || !(Param->EventChannel)) + return false; + + // Check Timer or force + if (Force || + (Param->UpdateInterval && Timeout( Param->UpdateTimeout, Param->UpdateInterval )) ) + { + // Post event + char Message[200]; + switch (Param->DataType) + { + case dtUnsigned16 : + sprintf( Message, "%s: %u\n", Param->Name, *((u_int16_t*)Param->Value) ); + break; + + case dtUnsigned32 : + sprintf( Message, "%s: %u\n", Param->Name, *((u_int32_t*)Param->Value) ); + break; + + case dtSigned16 : + sprintf( Message, "%s: %d\n", Param->Name, *((int16_t*)Param->Value) ); + break; + + case dtSigned32 : + sprintf( Message, "%s: %d\n", Param->Name, *((int32_t*)Param->Value) ); + break; + + case dtFloat32 : + sprintf( Message, "%s: %f\n", Param->Name, *((float*)Param->Value) ); + break; + + case dtString : + sprintf( Message, "%s: %s\n", Param->Name, (char*)Param->Value ); + break; + } + Output( Param->EventChannel, Message, strlen(Message) ); + + // Reset timer + if (Param->UpdateInterval) { + SetStartTime( &(Param->UpdateTimeout) ); + } + } + return true; +} +//--------------------------------------------------------------------------- diff --git a/DeviceCore.h b/DeviceCore.h new file mode 100644 index 0000000..cc37a95 --- /dev/null +++ b/DeviceCore.h @@ -0,0 +1,202 @@ +/* + * FunctionCore.h + * + * Created on: 18 May 2016 + * Author: wentzelc + */ + +#ifndef REDACORE_DEVICECORE_H_ +#define REDACORE_DEVICECORE_H_ + +// redA Libraries +#include "FunctionCore.h" + +// Standard C/C++ Libraries +/* no additional */ + +//--------------------------------------------------------------------------- + +// Enumerated types +typedef enum { dtUnsigned16 = 0, dtSigned16 = 1, dtUnsigned32 = 2, dtSigned32 = 3, dtFloat32 = 4, dtString = 5 } EDataType; + +// Constants +const char DataTypeName[][20] = { "Unsigned16", "Signed16", "Unsigned32", "Signed32", "Float32", "String" }; + +//--------------------------------------------------------------------------- + +// Structure prototypes +typedef struct SDevice TDevice; +typedef struct SDeviceParam TDeviceParam; + +// Devices with are polled +struct SDevice { + char * Name; + bool Online; + + TDeviceParam * FirstParam; + + TDevice * Next; +}; + +// Data parameters of devices +struct SDeviceParam { + char * Name; + EDataType DataType; + + bool Scan; + TChannel * EventChannel; + long UpdateInterval; + timeval UpdateTimeout; + + void * Value; + int Len; + bool Changed; + + void * SetValue; + int SetLen; + bool SetChanged; + + TDeviceParam * Next; +}; + +//--------------------------------------------------------------------------- + +class CDeviceCore : public CFunctionCore +{ +protected: + // Update + int UpdateInterval; + timeval UpdateTimeout; + + // Parameters + TDevice * FirstDevice; + TDevice * ActiveDevice; + + // Standard channels + TChannel * DeviceChannel; + TChannel * CmdChannel; + + // Poll + int PollStep; // Position in polling sequence + timeval PollWait; // Time at which last poll was done + long PollInterval; // Minimum delay between polls + + // Reply + bool WaitingForReply; // Command sent, waiting for reply + long ReplyTimeout; // Max waiting time for reply + + // Retry + int PollRetry; // No of polling retries that has timed out + int MaxRetries; // Max allowed retries + + // Manage Devices + bool DestroyDevice( TDevice ** Device ); + + // Find Devices + inline TDevice * GetDevice( const char * Name ) { + TDevice * Device = FirstDevice; + while (Device && strcmp( Device->Name, Name )) + Device = Device->Next; + return Device; + } + inline TDevice ** GetDevicePtr( const char * Name ) { + TDevice ** Device = &FirstDevice; + while (*Device && strcmp( (*Device)->Name, Name )) + Device = &((*Device)->Next); + return Device; + } + inline TDevice * GetNextOnlineDevice( TDevice * LastDevice ) { + TDevice * Device = LastDevice; + while (Device && !Device->Online) + Device = Device->Next; + return Device; + } + + // Manage Params + bool DestroyDeviceParam( TDeviceParam ** Param ); + + // Find Params + inline TDeviceParam * GetDeviceParam( TDevice * Device, const char * Name ) { + if (!Device) return NULL; + TDeviceParam * Param = Device->FirstParam; + while (Param && strcmp( Param->Name, Name )) + Param = Param->Next; + return Param; + } + inline TDeviceParam ** GetDeviceParamPtr( TDevice * Device, const char * Name ) { + if (!Device) return NULL; + TDeviceParam ** Param = &Device->FirstParam; + while (*Param && strcmp( (*Param)->Name, Name )) + Param = &((*Param)->Next); + return Param; + } + inline TDeviceParam * GetNextScanParam( TDevice * Device, TDeviceParam * LastParam = NULL ) { + if (!Device) return NULL; + TDeviceParam * Param = (LastParam)? LastParam->Next : Device->FirstParam; + while (Param && (!Param->Scan)) + Param = Param->Next; + return Param; + } + inline TDeviceParam * GetNextChangedParam( TDevice * Device, TDeviceParam * LastParam = NULL ) { + if (!Device) return NULL; + TDeviceParam * Param = (LastParam)? LastParam->Next : Device->FirstParam; + while (Param && (!Param->Changed)) + Param = Param->Next; + return Param; + } + inline TDeviceParam * GetNextSetChangedParam( TDevice * Device, TDeviceParam * LastParam = NULL ) { + if (!Device) return NULL; + TDeviceParam * Param = (LastParam)? LastParam->Next : Device->FirstParam; + while (Param && (!Param->SetChanged)) + Param = Param->Next; + return Param; + } + + // Tools + bool CompareParamString( const char * ParamValue, const int ParamLen, const char * Value, const int Len ); + + // Generate events + bool EventOutput( TDeviceParam * Param, bool Force ); + bool TimedParamEvents(); + + // Manage device + virtual bool DeviceOnline( TDevice * Device, bool Online ); + + // Handle Reply Timing + virtual void SetWaitForReply(); + virtual bool CheckReplyTimeout( int TimeoutPollStep ); + +public: + // Life cycle + CDeviceCore( const char * Name, CLogCore * pLog, EDebugLevel DebugLevel, int pOuputDisplay ); + ~CDeviceCore(); + + // Generate events + 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 ); + + // Manage Devices + TDevice * AddDevice( const char * DeviceName ); + bool DestroyDevice( const char * DeviceName ); + + // Manage Params + TDeviceParam * AddDeviceParam( TDevice * Device, const char * ParamName, EDataType DataType, int ParamLen = 1 ); + bool DestroyDeviceParam( TDevice * Device, const char * ParamName ); + + // 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 ); + + // 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 ); +}; +//--------------------------------------------------------------------------- + +#endif /* REDACORE_DEVICECORE_H_ */ diff --git a/FunctionCore.h b/FunctionCore.h index a25510b..76c2ae5 100644 --- a/FunctionCore.h +++ b/FunctionCore.h @@ -74,7 +74,7 @@ protected: public: // Life cycle - CFunctionCore( const char * ObjectName, CLogCore * pLog, EDebugLevel pDebugLevel, int pOuputDisplay ); + CFunctionCore( const char * FunctionName, CLogCore * pLog, EDebugLevel pDebugLevel, int pOuputDisplay ); virtual ~CFunctionCore(); // Miscellaneous