/* * FunctionCore.cpp * * Created on: 18 May 2016 * Author: wentzelc */ //--------------------------------------------------------------------------- // Standard C/C++ Libraries /* none */ // redA Libraries #include "ApplicationCore.h" #include "DeviceCore.h" //--------------------------------------------------------------------------- // Global Vars extern char * ProcessName; extern CApplication * Application; //--------------------------------------------------------------------------- //CFunctionCore * NewDeviceCore( const char * Name ) { // return (CFunctionCore*) new CDeviceCore( Name ); //} //--------------------------------------------------------------------------- CDeviceCore::CDeviceCore( const char * pName, const char * pType ) : CFunctionCore( pName, pType ) { // Clear Parameters FirstDevice = NULL; ActiveDevice = NULL; // Standard channels DeviceChannel = NULL; CmdChannel = NULL; EventChannel = NULL; // Polling PollStep = 0; PollInterval = 250; SetStartTime( &PollWait ); WaitingForReply = false; ReplyTimeout = 200; PollRetry = 0; MaxRetries = 3; // Data Structures Config = NULL; DeviceInit = true; } //--------------------------------------------------------------------------- CDeviceCore::~CDeviceCore() { // Destroy Params while (FirstDevice) DestroyDevice( &FirstDevice ); } //--------------------------------------------------------------------------- bool CDeviceCore::Init( CDataMember * FunctionConfig ) { char * ConfigName = NULL; CDataMember * PollConfig = NULL; int IntVal1; int IntVal2; // Call Previous load config 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" ); Config = Application->Config->GetChild( ConfigName, true ); } if (Config->isNull()) Config->SetObject(); // Load Polling configuration PollConfig = Config->GetChild( "Polling", true ); if (PollConfig->isNull()) PollConfig->SetObject(); IntVal1 = PollConfig->GetChInt( "PollInterval", 500, true ); SetPollParam( IntVal1 ); IntVal1 = PollConfig->GetChInt( "ReplyTimeout", 250, true ); IntVal2 = PollConfig->GetChInt( "MaxRetries", 3, true ); SetReplyParam( IntVal1, IntVal2 ); Log->Message( LogLevel, dlMedium, "%s/%s: Set Polling param - Int:%d, TO:%d, Max:%d, Up:%d", 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; } //--------------------------------------------------------------------------- bool CDeviceCore::SetPollParam( int pPollInterval ) { PollInterval = pPollInterval; return true; } //--------------------------------------------------------------------------- bool CDeviceCore::SetReplyParam( int pReplyTimeout, int pMaxRetries ) { ReplyTimeout = pReplyTimeout; MaxRetries = pMaxRetries; 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; if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Device '%s' %s", ProcessName, 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 if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - %s timeout, retry [%d]", ProcessName, Name, DeviceChannel->Name, ActiveDevice->Name, PollRetry ); } else { // Log Event if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - %s timeout, max [%d]", ProcessName, 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, const char * Type ) { TDevice ** Device = &FirstDevice; if (!DeviceName || !*DeviceName) return NULL; while (*Device && strcmp( DeviceName, (*Device)->Name )) Device = &((*Device)->Next); // Create if not found if (!*Device) { *Device = (TDevice*)malloc( sizeof(TDevice) ); memset( *Device, 0x0, sizeof(TDevice) ); (*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' (%s)", ProcessName, Name, DeviceName, (Type)? Type : "no type" ); return *Device; } //--------------------------------------------------------------------------- bool CDeviceCore::DestroyDevice( TDevice ** Device ) { TDevice * NextDevice = NULL; // Validate Device if (!Device || !*Device) return false; // Save reference to next Device NextDevice = (*Device)->Next; // Destroy Device structure if ((*Device)->Name) free( (*Device)->Name ); if ((*Device)->Type) free( (*Device)->Type ); // Destroy paramters while ((*Device)->FirstParam) { DestroyDeviceParam( &((*Device)->FirstParam) ); } // Destroy Device free( *Device ); // Remove from list *Device = NextDevice; // Device successfully destroyed return true; } //--------------------------------------------------------------------------- TDeviceParam * CDeviceCore::AddDeviceParam( TDevice * Device, const char * ParamName, EDeviceDataType 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; default : break; } } // Mark as updated (*Param)->Changed = true; // Report creation if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Param added - '%s' (%s)", ProcessName, Name, ParamName, DataTypeName[DataType] ); return *Param; } //--------------------------------------------------------------------------- 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; if (Log) Log->Message( LogLevel, dlLow, "%s/%s: '%s' %s - %u", ProcessName, 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; if (Log) Log->Message( LogLevel, dlLow, "%s/%s: '%s' %s - %u", ProcessName, 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; if (Log) Log->Message( LogLevel, dlLow, "%s/%s: '%s' %s - %f", ProcessName, 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; if (Log) Log->Message( LogLevel, dlLow, "%s/%s: '%s' %s - %d", ProcessName, 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; if (Log) Log->Message( LogLevel, dlLow, "%s/%s: '%s' %s - %d", ProcessName, 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; if (Log) Log->Message( LogLevel, dlLow, "%s/%s: '%s' %s - %f", ProcessName, 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; switch (Param->DataType) { case dtString : // 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; if (Log) Log->Message( LogLevel, dlLow, "%s/%s: '%s' %s - %s", ProcessName, Name, Param->Name, ((Init)? "initialised" : "changed"), (char*)Param->Value ); } break; default : // Invalid Data Type return false; } // 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::SetValue( TDeviceParam * Param, const char * Value, const int Len, bool Force ) { u_int32_t UnsignedVal; int32_t SignedVal; float FloatVal; char * TempStr; bool UseTempStr = false; // Validate if (!Param || !Value || !Len) return false; // Check if string if (Param->DataType == dtString) { // Simply set string SetStringValue( Param, Value, Len, Force ); } else { // Ensure string is zero terminated if (Value[Len] != 0) { TempStr = (char *)malloc( Len+1 ); memcpy( TempStr, Value, Len ); TempStr[Len] = 0; UseTempStr = true; } // Convert to correct type switch (Param->DataType) { case dtUnsigned16 : case dtUnsigned32 : UnsignedVal = (u_int32_t)strtoul( ((UseTempStr)? TempStr : Value), NULL, 10 ); SetUnsignedValue( Param, UnsignedVal, Force ); break; case dtSigned16 : case dtSigned32 : SignedVal = (u_int32_t)strtol( ((UseTempStr)? TempStr : Value), NULL, 10 ); SetUnsignedValue( Param, SignedVal, Force ); break; case dtFloat32 : FloatVal = (u_int32_t) strtof( ((UseTempStr)? TempStr : Value), NULL ); SetUnsignedValue( Param, FloatVal, Force ); break; default : return false; } // Clear memory if (UseTempStr) { free( TempStr ); } } return true; } //--------------------------------------------------------------------------- bool CDeviceCore::GetValue( TDeviceParam * Param, char * Value, int &Len ) { // Validate if (!Param || !Value) return false; // Check if return value longer than actual value switch (Param->DataType) { case dtUnsigned16 : sprintf( Value, "%u", (*((u_int16_t*)Param->Value)) ); break; case dtUnsigned32 : sprintf( Value, "%u", (*((u_int32_t*)Param->Value)) ); break; case dtSigned16 : sprintf( Value, "%d", (*((int16_t*)Param->Value)) ); break; case dtSigned32 : sprintf( Value, "%d", (*((int32_t*)Param->Value)) ); break; case dtFloat32 : sprintf( Value, "%f", (*((float*)Param->Value)) ); break; case dtString : if (Len < Param->Len) { // Only copy requested no of chars memcpy( Value, Param->Value, Len ); Value[ Len ] = 0; } else { memcpy( Value, Param->Value, Param->Len ); Value[ Param->Len ] = 0; } break; default : break; } 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::SetParamAccess( TDeviceParam * Param, bool Read, bool Write ) { if (!Param) return false; Param->Read = Read; Param->Write = Write; return true; } //--------------------------------------------------------------------------- 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; } //--------------------------------------------------------------------------- bool CDeviceCore::TimedParamEvents() { TDevice * Device = NULL; TDeviceParam * Param = NULL; // Loop through all devices Device = FirstDevice; while (Device) { // Loop through all Read parameters while ((Param = GetNextReadParam( Device, Param ))) { EventOutput( Param, false ); } Device = Device->Next; } return true; } //--------------------------------------------------------------------------- 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 ) { // Validate if (!Param || !(Param->EventChannel)) return false; // Check Timer or force if (Force || (Param->EventInterval && Timeout( Param->EventTimeout, Param->EventInterval )) ) { // 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; default : break; } Output( Param->EventChannel, Message, strlen(Message) ); // Reset timer if (Param->EventInterval) { SetStartTime( &(Param->EventTimeout) ); } } return true; } //---------------------------------------------------------------------------