diff --git a/DeviceCore.cpp b/DeviceCore.cpp index de813fa..d6a8148 100644 --- a/DeviceCore.cpp +++ b/DeviceCore.cpp @@ -36,6 +36,7 @@ CDeviceCore::CDeviceCore( const char * pName, const char * pType ) : CFunctionCo WaitingForReply = false; ReplyTimeout = 200; + InvalidReply = false; PollRetry = 0; MaxRetries = 3; @@ -115,34 +116,38 @@ bool CDeviceCore::InitDevices( CDataMember * FunctionConfig ) CDataMember * DeviceData = NULL; TDevice * Device = NULL; char * DeviceName = NULL; + int DeviceID = 0; + char * DeviceAddr = NULL; char * DeviceType = NULL; // Load Device Types DeviceData = Config->GetChFirstChild( "DeviceTypes", true ); while (DeviceData) { - DeviceName = (char*)DeviceData->GetName(); - Device = AddDeviceType( DeviceName ); + DeviceType = (char*)DeviceData->GetName(); + Device = AddDeviceType( DeviceType ); - if (DeviceData->isString()) { - if (JSONparse->ReadFromFile( DeviceName, DeviceData->GetStr() )) { // Contains file reference - InitDeviceParams( Device, ConfigTypes->GetChild( DeviceName ) ); - InitParamGroups( Device, ConfigTypes->GetChild( DeviceName ) ); - JSONparse->WriteToFile( DeviceName, DeviceData->GetStr() ); + if (Device) { + if (DeviceData->isString()) { + if (JSONparse->ReadFromFile( DeviceType, DeviceData->GetStr() )) { // Contains file reference + InitDeviceParams( Device, ConfigTypes->GetChild( DeviceType ) ); + InitParamGroups( Device, ConfigTypes->GetChild( DeviceType ) ); + JSONparse->WriteToFile( DeviceType, DeviceData->GetStr() ); + } + else { + if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Fail to load device type '%s' from file: '%s'", + ProcessName, Name, DeviceType, DeviceData->GetStr() ); + } + } + else if (DeviceData->isObject()) { + InitDeviceParams( Device, DeviceData ); // Contains definition + InitParamGroups( Device, DeviceData ); } else { - if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Fail to load device type '%s' from file: '%s'", - ProcessName, Name, DeviceName, DeviceData->GetStr() ); + if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Invalid device type config for '%s'", + ProcessName, Name, DeviceType ); } } - 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, DeviceName ); - } DeviceData = DeviceData->GetNextPeer(); } @@ -151,12 +156,15 @@ bool CDeviceCore::InitDevices( CDataMember * FunctionConfig ) while (DeviceData) { DeviceName = (char*)DeviceData->GetName(); - DeviceType = (char*)DeviceData->GetChStr( "Type" ); - Device = AddDevice( DeviceName, DeviceType ); - - InitDeviceParams( Device, DeviceData ); - InitParamGroups( Device, DeviceData ); + DeviceID = DeviceData->GetChInt( "ID", 0 ); + DeviceAddr = (char*)DeviceData->GetChStr( "Address", NULL ); + DeviceType = (char*)DeviceData->GetChStr( "Type", NULL ); + Device = AddDevice( DeviceName, DeviceType, DeviceID, DeviceAddr ); + if (Device) { + InitDeviceParams( Device, DeviceData ); + InitParamGroups( Device, DeviceData ); + } DeviceData = DeviceData->GetNextPeer(); } return true; @@ -179,23 +187,24 @@ bool CDeviceCore::InitDeviceParams( TDevice * Device, CDataMember * DeviceConfi // Copy Template Template = (Device->Template)? Device->Template->FirstParam : NULL; - while (Template) { + 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)) { + 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)) { + 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) { + 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 ); @@ -225,17 +234,17 @@ bool CDeviceCore::InitDeviceParams( TDevice * Device, CDataMember * DeviceConfi SetParamEvent( Param, EventOut, EventInt ); if ((InitVal = ParamData->GetChild( "InitValue", false ))) { - if ((DataType == dtUnsigned16) || (DataType == dtUnsigned32)) { + if ((DataType == dtUnsigned16) || (DataType == dtUnsigned32_HL) || (DataType == dtUnsigned32_LH)) { UpdateUnsignedValue( Param, InitVal->GetInt(0), Read ); if (Write) SetUnsignedValue( Param, InitVal->GetInt(0), true ); } - else if ((DataType == dtSigned16) || (DataType == dtSigned32)) { + else if ((DataType == dtSigned16) || (DataType == dtSigned32_HL) || (DataType == dtSigned32_LH)) { UpdateSignedValue( Param, InitVal->GetInt(0), Read ); if (Write) SetSignedValue( Param, InitVal->GetInt(0), true ); } - else if (DataType == dtFloat32) { + else if ((DataType == dtFloat32_L) || (DataType == dtFloat32_B)) { UpdateFloatValue( Param, InitVal->GetFloat(0), Read ); if (Write) SetFloatValue( Param, InitVal->GetFloat(0), true ); @@ -338,43 +347,50 @@ void CDeviceCore::SetWaitForReply() // Set flag WaitingForReply = true; + InvalidReply = false; } //--------------------------------------------------------------------------- -bool CDeviceCore::CheckReplyTimeout( int TimeoutPollStep ) +void CDeviceCore::ValidReplyReceived() +{ + // Reset parameters for next command + WaitingForReply = false; + InvalidReply = false; + PollRetry = 0; +} +//--------------------------------------------------------------------------- + +bool CDeviceCore::CheckReplyTimeout() { // Check for Reply timeout - if (WaitingForReply && Timeout( PollWait, ReplyTimeout )) + if (!WaitingForReply || !Timeout( PollWait, ReplyTimeout )) { + // No timeout + return false; + } + + // Update flags + WaitingForReply = false; + InvalidReply = false; + PollRetry++; + + // Handle No Reply / Retry + if (PollRetry > MaxRetries) { - // Increment retries - PollRetry++; + if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Device '%s' %s - Max retries", + ProcessName, Name, DeviceChannel->Name, ActiveDevice->Name, + ((InvalidReply)? "invalid reply" : "timeout"), PollRetry ); - // Handle No Reply / Retry - if (PollRetry < MaxRetries) { - // Log Event - if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Device '%s' timeout, retry [%d]", - ProcessName, Name, DeviceChannel->Name, ActiveDevice->Name, PollRetry ); - } - else { - // Log Event - if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Device '%s' timeout, max [%d]", - ProcessName, Name, DeviceChannel->Name, ActiveDevice->Name, PollRetry ); - - // Set Device Offline - DeviceOnline( ActiveDevice, false ); - PollStep = TimeoutPollStep; - } - - // Reset flag - retry - WaitingForReply = false; + // Set Device Offline + DeviceOnline( ActiveDevice, false ); + PollRetry = 0; return true; } - else - { - // Reset retries - PollRetry = 0; - return false; - } + + // Try again + if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Device '%s' %s, Retry %d/%d", + ProcessName, Name, DeviceChannel->Name, ActiveDevice->Name, + ((InvalidReply)? "invalid reply" : "timeout"), PollRetry, MaxRetries ); + return false; } //--------------------------------------------------------------------------- @@ -404,18 +420,36 @@ TDevice * CDeviceCore::AddDeviceType( const char * DeviceTypeName ) } //--------------------------------------------------------------------------- -TDevice * CDeviceCore::AddDevice( const char * DeviceName, const char * Type ) +TDevice * CDeviceCore::AddDevice( const char * DeviceName, const char * DeviceType, const int DeviceID, const char * DeviceAddress ) { - TDevice ** Device = GetDevicePtr( DeviceName ); + TDevice ** Device = &FirstDevice; - if (!Device) { - if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Could not add device '%s' (%s)", ProcessName, Name, - ((DeviceName)? DeviceName : "[device]"), ((Type)? Type : "no type") ); + if (!DeviceName || !*DeviceName || (DeviceAddress && !*DeviceAddress)) { + if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Could not add device '%s' - Invalid parameters, Tp:'%s' ID:%d, Addr:'%s'", + ProcessName, Name, ((DeviceName)? DeviceName : "[no name]"), ((DeviceType)? DeviceType : "[none]"), + DeviceID, ((DeviceAddress)? DeviceAddress : "[none]") ); return NULL; } - else if (*Device) { - if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Device type '%s' (%s) already exists", ProcessName, Name, - DeviceName, (((*Device)->Type)? (*Device)->Type : "no type") ); + + // Find device matching by any parameter + while (*Device && strcasecmp((*Device)->Name, DeviceName) && (!DeviceID || + (*Device)->ID != DeviceID) && (!DeviceAddress || strcasecmp((*Device)->Address, DeviceAddress))) + Device = &((*Device)->Next); + + if (*Device) { + if (!strcasecmp((*Device)->Name, DeviceName)) { + if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Could not add device '%s' - Name already exists", + ProcessName, Name, DeviceName ); + } + else if (DeviceID && ((*Device)->ID == DeviceID)) { + if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Could not add device '%s' - ID '%d' already exists", + ProcessName, Name, DeviceName, DeviceID ); + } + else if (DeviceAddress && !strcasecmp((*Device)->Address, DeviceAddress)) { + if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Could not add device '%s' - Address '%s' already exists", + ProcessName, Name, DeviceName, DeviceAddress ); + } + return NULL; } else { *Device = new TDevice; @@ -423,15 +457,23 @@ TDevice * CDeviceCore::AddDevice( const char * DeviceName, const char * Type ) (*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 ); + (*Device)->ID = DeviceID; - (*Device)->Template = GetDeviceType( Type ); + if (DeviceAddress) { + (*Device)->Address = (char *)malloc( strlen( DeviceAddress )+1 ); + strcpy( (*Device)->Address, DeviceAddress ); } - if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Added device '%s' (%s%s)", ProcessName, Name, - DeviceName, ((Type)? Type : "no type"), (((*Device)->Template)? "*" : "") ); + if (DeviceType && *DeviceType) { + (*Device)->Type = (char *)malloc( strlen( DeviceType )+1 ); + strcpy( (*Device)->Type, DeviceType ); + + (*Device)->Template = GetDeviceType( DeviceType ); + } + + if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Added device '%s' - Tp:'%s'%s, ID:%d, Addr:'%s'", + ProcessName, Name, DeviceName, ((DeviceType)? DeviceType : "[none]"), + (((*Device)->Template)? "*" : ""), DeviceID, ((DeviceAddress)? DeviceAddress : "[none]") ); } return *Device; } @@ -451,6 +493,8 @@ bool CDeviceCore::DestroyDevice( TDevice ** Device ) // Destroy Device structure if ((*Device)->Name) free( (*Device)->Name ); + if ((*Device)->Address) + free( (*Device)->Address ); if ((*Device)->Type) free( (*Device)->Type ); @@ -479,15 +523,17 @@ TDeviceParam * CDeviceCore::AddDeviceParam( TDevice * Device, const char * Param if (!Param) { // Invalid device/param - if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Param '%s/%s' cannot be created", ProcessName, Name, - ((!Device)? "[device]" : (Device->Name)? Device->Name : Device->Type), - ((!ParamName)? "[param]" : ParamName)); + if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Could not add Param '%s/%s' - Invalid parameters, Tp:'%s'", + ProcessName, Name, ((!Device)? "[no name]" : (Device->Name)? Device->Name : Device->Type), + ((!ParamName)? "[no name]" : ParamName), DataTypeName[DataType]); return NULL; } else if (*Param) { // Parameter already exists - if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Param '%s/%s' already exists", ProcessName, Name, - ((Device->Name)? Device->Name : Device->Type), ParamName, DataTypeName[DataType]); + if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Could not add Param '%s/%s' - Already exists", + ProcessName, Name, ((Device->Name)? Device->Name : Device->Type), + ParamName, DataTypeName[DataType]); + return NULL; } else { // Create register @@ -526,7 +572,8 @@ TDeviceParam * CDeviceCore::AddDeviceParam( TDevice * Device, const char * Param (*Param)->SetLen = sizeof(int16_t); break; - case dtUnsigned32 : + case dtUnsigned32_HL : + case dtUnsigned32_LH : // Create Value pointer (*Param)->Value = (u_int32_t*)malloc( sizeof(u_int32_t) ); *((u_int32_t*)(*Param)->Value) = 0; @@ -538,7 +585,8 @@ TDeviceParam * CDeviceCore::AddDeviceParam( TDevice * Device, const char * Param (*Param)->SetLen = sizeof(u_int32_t); break; - case dtSigned32 : + case dtSigned32_HL : + case dtSigned32_LH : // Create Value pointer (*Param)->Value = (int32_t*)malloc( sizeof(int32_t) ); *((int32_t*)(*Param)->Value) = 0; @@ -550,7 +598,8 @@ TDeviceParam * CDeviceCore::AddDeviceParam( TDevice * Device, const char * Param (*Param)->SetLen = sizeof(int32_t); break; - case dtFloat32 : + case dtFloat32_L : + case dtFloat32_B : // Create Value pointer (*Param)->Value = (float*)malloc( sizeof(float) ); *((float*)(*Param)->Value) = 0.0; @@ -579,8 +628,9 @@ TDeviceParam * CDeviceCore::AddDeviceParam( TDevice * Device, const char * Param } (*Param)->Changed = true; - if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Added param '%s/%s' (%s)", ProcessName, Name, - ((Device->Name)? Device->Name : Device->Type), ParamName, DataTypeName[DataType]); + if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Added param '%s/%s', Tp:'%s'", + ProcessName, Name, ((Device->Name)? Device->Name : Device->Type), + ParamName, DataTypeName[DataType]); } return *Param; } @@ -621,8 +671,8 @@ TDeviceParamGroup * CDeviceCore::AddParamGroup( TDevice * Device, const char * G TDeviceParamGroup ** ParamGroup = GetParamGroupPtr( Device, GroupName ); if (!ParamGroup) { - if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Could not add param group '%s'", ProcessName, Name, - ((!Device)? "[device]" : (Device->Name)? Device->Name : Device->Type), + if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Could not add param group '%s'", + ProcessName, Name, ((!Device)? "[device]" : (Device->Name)? Device->Name : Device->Type), ((GroupName)? GroupName : "[group]") ); return NULL; } @@ -683,19 +733,20 @@ TDeviceParamItem * CDeviceCore::AddParamItem( TDeviceParamGroup * Group, const c if (!Item) { // 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)); + 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)); 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 ); + 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 ); + 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 ); } else { *Item = new TDeviceParamItem; @@ -707,8 +758,9 @@ TDeviceParamItem * CDeviceCore::AddParamItem( TDeviceParamGroup * Group, const c if (Param->Write) Group->Write = true; - 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 ); + 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 ); } return *Item; } @@ -792,7 +844,8 @@ bool CDeviceCore::UpdateUnsignedValue( TDeviceParam * Param, const u_int32_t Val } break; - case dtUnsigned32 : + case dtUnsigned32_HL : + case dtUnsigned32_LH : if (Init || (*((u_int32_t*)Param->Value) != Value)) { // Set new value & mark change @@ -808,7 +861,9 @@ bool CDeviceCore::UpdateUnsignedValue( TDeviceParam * Param, const u_int32_t Val } break; - case dtFloat32 : // Special case, where float value is stored in Integer memory (e.g. modbus register) + case dtFloat32_L : + case dtFloat32_B : + // 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 @@ -863,7 +918,8 @@ bool CDeviceCore::UpdateSignedValue( TDeviceParam * Param, const int32_t Value, } break; - case dtSigned32 : + case dtSigned32_HL : + case dtSigned32_LH : if (Init || (*((int32_t*)Param->Value) != Value)) { // Set new value & mark change @@ -902,7 +958,8 @@ bool CDeviceCore::UpdateFloatValue( TDeviceParam * Param, const float Value, boo switch (Param->DataType) { - case dtFloat32 : + case dtFloat32_L : + case dtFloat32_B : if (Init || (*((float*)Param->Value) != Value)) { // Set new value & mark change @@ -999,7 +1056,8 @@ bool CDeviceCore::SetUnsignedValue( TDeviceParam * Param, const u_int32_t Value, } break; - case dtUnsigned32 : + case dtUnsigned32_HL : + case dtUnsigned32_LH : if (Force || (*((u_int32_t*)Param->SetValue) != Value)) { // Set new value @@ -1038,7 +1096,8 @@ bool CDeviceCore::SetSignedValue( TDeviceParam * Param, const int32_t Value, boo } break; - case dtSigned32 : + case dtSigned32_HL : + case dtSigned32_LH : if (Force || (*((int32_t*)Param->SetValue) != Value)) { // Set new value @@ -1066,7 +1125,8 @@ bool CDeviceCore::SetFloatValue( TDeviceParam * Param, const float Value, bool F switch (Param->DataType) { - case dtFloat32 : + case dtFloat32_L : + case dtFloat32_B : if (Force || (*((float*)Param->SetValue) != Value)) { // Set new value @@ -1147,18 +1207,21 @@ bool CDeviceCore::SetValue( TDeviceParam * Param, const char * Value, const int switch (Param->DataType) { case dtUnsigned16 : - case dtUnsigned32 : + case dtUnsigned32_HL : + case dtUnsigned32_LH : UnsignedVal = (u_int32_t)strtoul( ((UseTempStr)? TempStr : Value), NULL, 10 ); SetUnsignedValue( Param, UnsignedVal, Force ); break; case dtSigned16 : - case dtSigned32 : + case dtSigned32_HL : + case dtSigned32_LH : SignedVal = (u_int32_t)strtol( ((UseTempStr)? TempStr : Value), NULL, 10 ); SetUnsignedValue( Param, SignedVal, Force ); break; - case dtFloat32 : + case dtFloat32_L : + case dtFloat32_B : FloatVal = (u_int32_t) strtof( ((UseTempStr)? TempStr : Value), NULL ); SetUnsignedValue( Param, FloatVal, Force ); break; @@ -1189,7 +1252,8 @@ bool CDeviceCore::GetValue( TDeviceParam * Param, char * Value, int &Len ) sprintf( Value, "%u", (*((u_int16_t*)Param->Value)) ); break; - case dtUnsigned32 : + case dtUnsigned32_HL : + case dtUnsigned32_LH : sprintf( Value, "%u", (*((u_int32_t*)Param->Value)) ); break; @@ -1197,11 +1261,13 @@ bool CDeviceCore::GetValue( TDeviceParam * Param, char * Value, int &Len ) sprintf( Value, "%d", (*((int16_t*)Param->Value)) ); break; - case dtSigned32 : + case dtSigned32_HL : + case dtSigned32_LH : sprintf( Value, "%d", (*((int32_t*)Param->Value)) ); break; - case dtFloat32 : + case dtFloat32_L : + case dtFloat32_B : sprintf( Value, "%f", (*((float*)Param->Value)) ); break; @@ -1333,7 +1399,7 @@ int CDeviceCore::HandleCommand( const char *ChannelName, const char * Data, cons // Get device name GetCmdParam( NextParam, ParamName, &NextParam ); - if (!(Device = GetDevice( ParamName ))) { + if (!(Device = GetDeviceByName( ParamName ))) { // Unknown Parameters Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown 'get' Device: '%s'", ProcessName, Name, ChannelName, ParamName ); @@ -1382,7 +1448,7 @@ int CDeviceCore::HandleCommand( const char *ChannelName, const char * Data, cons // Get Device name GetCmdParam( NextParam, ParamName, &NextParam ); - if (!(Device = GetDevice( ParamName ))) { + if (!(Device = GetDeviceByName( ParamName ))) { // Unknown Parameters Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown 'set' Device: '%s'", ProcessName, Name, ChannelName, ParamName ); @@ -1437,7 +1503,7 @@ int CDeviceCore::HandleCommand( const char *ChannelName, const char * Data, cons // Get Device name GetCmdParam( NextParam, ParamName, &NextParam ); - if (!(Device = GetDevice( ParamName ))) { + if (!(Device = GetDeviceByName( ParamName ))) { // Unknown Parameters Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown 'status' Device: '%s'", ProcessName, Name, ChannelName, ParamName ); @@ -1488,7 +1554,8 @@ bool CDeviceCore::EventOutput( TDeviceParam * Param, bool Force ) sprintf( Message, "%s: %u\n", Param->Name, *((u_int16_t*)Param->Value) ); break; - case dtUnsigned32 : + case dtUnsigned32_HL : + case dtUnsigned32_LH : sprintf( Message, "%s: %u\n", Param->Name, *((u_int32_t*)Param->Value) ); break; @@ -1496,11 +1563,13 @@ bool CDeviceCore::EventOutput( TDeviceParam * Param, bool Force ) sprintf( Message, "%s: %d\n", Param->Name, *((int16_t*)Param->Value) ); break; - case dtSigned32 : + case dtSigned32_HL : + case dtSigned32_LH : sprintf( Message, "%s: %d\n", Param->Name, *((int32_t*)Param->Value) ); break; - case dtFloat32 : + case dtFloat32_L : + case dtFloat32_B : sprintf( Message, "%s: %f\n", Param->Name, *((float*)Param->Value) ); break; diff --git a/DeviceCore.h b/DeviceCore.h index 9d05aae..b6fcdde 100644 --- a/DeviceCore.h +++ b/DeviceCore.h @@ -18,11 +18,13 @@ //--------------------------------------------------------------------------- // Enumerated types -typedef enum { dtNone = 0, dtUnsigned16 = 1, dtSigned16 = 2, dtUnsigned32 = 3, dtSigned32 = 4, dtFloat32 = 5, dtString = 6 } EDeviceDataType; +typedef enum { dtNone = 0, dtUnsigned16 = 1, dtSigned16 = 2, dtUnsigned32_HL = 3, dtUnsigned32_LH = 4, + dtSigned32_HL = 5, dtSigned32_LH = 6, dtFloat32_L = 7, dtFloat32_B = 8, dtString = 9 } EDeviceDataType; // Constants -const char DataTypeCount = 6; -const char DataTypeName[][20] = { "None", "Unsigned16", "Signed16", "Unsigned32", "Signed32", "Float32", "String" }; +const char DataTypeCount = 10; +const char DataTypeName[][20] = { "None", "Unsigned16", "Signed16", "Unsigned32_HL", "Unsigned32_LH", + "Signed32_HL", "Signed32_LH", "Float32_L", "Float32_B", "String" }; //--------------------------------------------------------------------------- @@ -36,8 +38,12 @@ typedef struct SDeviceParamItem TDeviceParamItem; // Devices with are polled struct SDevice { - // Device definition + // Device Identification char * Name = NULL; + int ID = 0; + char * Address = NULL; + + // Device Type char * Type = NULL; TDevice * Template = NULL; @@ -131,6 +137,7 @@ protected: // Reply bool WaitingForReply; // Command sent, waiting for reply + bool InvalidReply; // Invalid reply received long ReplyTimeout; // Max waiting time for reply // Retry @@ -154,17 +161,41 @@ protected: } // Find Devices - inline TDevice * GetDevice( const char * Name ) { - TDevice ** Device = GetDevicePtr(Name); + inline TDevice * GetDeviceByName( const char * pName ) { + TDevice ** Device = GetDevicePtrByName( pName ); return (Device)? *Device : NULL; } - inline TDevice ** GetDevicePtr( const char * Name ) { - if (!Name || !*Name) return NULL; + inline TDevice ** GetDevicePtrByName( const char * pName ) { + if (!pName || !*pName) return NULL; TDevice ** Device = &FirstDevice; - while (*Device && strcasecmp( (*Device)->Name, Name )) + while (*Device && strcasecmp( (*Device)->Name, pName )) Device = &((*Device)->Next); return Device; } + + inline TDevice * GetDeviceByID( int pID ) { + TDevice ** Device = GetDevicePtrByID( pID ); + return (Device)? *Device : NULL; + } + inline TDevice ** GetDevicePtrByID( int pID ) { + TDevice ** Device = &FirstDevice; + while (*Device && ((*Device)->ID != pID )) + Device = &((*Device)->Next); + return Device; + } + + inline TDevice * GetDeviceByAddr( const char * Address ) { + TDevice ** Device = GetDevicePtrByName(Address); + return (Device)? *Device : NULL; + } + inline TDevice ** GetDevicePtrByAddr( const char * Address ) { + if (!Address || !*Address) return NULL; + TDevice ** Device = &FirstDevice; + while (*Device && strcasecmp( (*Device)->Address, Address )) + Device = &((*Device)->Next); + return Device; + } + 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 ))))) @@ -264,7 +295,8 @@ protected: // Handle Reply Timing virtual void SetWaitForReply(); - virtual bool CheckReplyTimeout( int TimeoutPollStep ); + virtual void ValidReplyReceived(); + virtual bool CheckReplyTimeout(); public: // Life cycle @@ -292,9 +324,9 @@ public: } // Manage Devices - TDevice * AddDevice( const char * DeviceName, const char * Type = NULL ); + TDevice * AddDevice( const char * DeviceName, const char * Type = NULL, const int ID = 0, const char * Address = NULL ); inline bool DestroyDevice( const char * DeviceName ) { - TDevice ** Device = GetDevicePtr(DeviceName); + TDevice ** Device = GetDevicePtrByName(DeviceName); return (Device)? DestroyDevice( Device ) : false; } @@ -335,10 +367,9 @@ public: return SetStringValue( Param, Value, strlen(Value), Force ); }; - // Handle Interface Commands bool GetCmdParam( const char * Start, char * Param, char ** NextParam ); - int HandleCommand( const char *ChannelName, const char * Data, const int MaxLen ); + 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 ); diff --git a/FunctionCore.cpp b/FunctionCore.cpp index 055fd40..d90682d 100644 --- a/FunctionCore.cpp +++ b/FunctionCore.cpp @@ -356,7 +356,7 @@ int CFunctionCore::Output( const char * ChannelName, const char * Data, int Len } //--------------------------------------------------------------------------- -int CFunctionCore::Output( const TChannel * Channel, const char * Data, int Len ) +int CFunctionCore::Output( const TChannel * Channel, const char * Data, int Len, int OutputFormat ) { TChannelLink * OutChannel = NULL; int TempLen = 0; @@ -375,7 +375,7 @@ int CFunctionCore::Output( const TChannel * Channel, const char * Data, int Len } // Log event - if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, Len, "%s/%s: Channel '%s' - OUT:", + if (Log) Log->Output( LogLevel, dlHigh, ((!OutputFormat)? LogOutput : OutputFormat), Data, Len, "%s/%s: Channel '%s' - OUT:", ProcessName, Name, Channel->Name ); // Pass output to all linked inputs diff --git a/FunctionCore.h b/FunctionCore.h index d659602..37c75f0 100644 --- a/FunctionCore.h +++ b/FunctionCore.h @@ -83,7 +83,7 @@ protected: } // Data Input/Output - virtual int Output( const TChannel * Channel, const char * Data, int Len ); + virtual int Output( const TChannel * Channel, const char * Data, int Len, int OutputFormat = loNone ); virtual bool PullInput( TChannel * Channel ); public: diff --git a/SelectableCore.cpp b/SelectableCore.cpp index c8dd01f..425f42a 100644 --- a/SelectableCore.cpp +++ b/SelectableCore.cpp @@ -2340,19 +2340,19 @@ int CSelectableCore::Input( const char * ChannelName, const char * Data, int Len // Get Channel if (!(Channel = GetChannel( ChannelName ))) { // Channel not found - if (Log) Log->Message( LogLevel, dlHigh, "%s: Channel '%s' - Input rejected, Channel not found", + if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Input rejected, Channel not found", ProcessName, Name, ChannelName ); return 0; } else if (!Channel->InputEnabled) { // Channel disabled - if (Log) Log->Message( LogLevel, dlHigh, "%s: Channel '%s' - Input rejected, Channel input disabled", + if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Input rejected, Channel input disabled", ProcessName, Name, ChannelName ); return 0; } // Log event - if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, Len, "%s: Channel '%s' - IN:", + if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, Len, "%s/%s: Channel '%s' - IN:", ProcessName, Name, ChannelName ); // Find Linked handle @@ -2371,7 +2371,7 @@ int CSelectableCore::Input( const char * ChannelName, const char * Data, int Len if (!HandleCount) { // Handle not found - if (Log) Log->Message( LogLevel, dlHigh, "%s: Channel '%s' - Input rejected, No Handles not found", + if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Input rejected, No Handles not found", ProcessName, Name, ChannelName ); return 0; }