Major Update:

- FunctionCore:
  - Add OutputFormat param on Output() method - override output format
- SelectableCore:
  - Update Log output formats (process/functionblock)
- DeviceCore:
  - Updated device data format (different byte sequences)
  - Added ID & Address fields to TDevice struct
  - Add search methods for ID & Address
  - Update AddDevice() method to check for duplicate ID & address
  - Handle Invalid reply different from reply timeout
  - Add methods ValidReplyReceived() for standardise operation
  - Bug fix: DeviceTypes added as to Device List!
  - Bug fix: Check if Device/DeviceType created before adding params
  - Added correct handling of new Device Data types (LH & HL)
  - Updated log messages
This commit is contained in:
Charl Wentzel
2018-12-16 00:42:43 +02:00
parent f1be4e9540
commit c5da842ac1
5 changed files with 231 additions and 131 deletions

View File

@@ -36,6 +36,7 @@ CDeviceCore::CDeviceCore( const char * pName, const char * pType ) : CFunctionCo
WaitingForReply = false; WaitingForReply = false;
ReplyTimeout = 200; ReplyTimeout = 200;
InvalidReply = false;
PollRetry = 0; PollRetry = 0;
MaxRetries = 3; MaxRetries = 3;
@@ -115,24 +116,27 @@ bool CDeviceCore::InitDevices( CDataMember * FunctionConfig )
CDataMember * DeviceData = NULL; CDataMember * DeviceData = NULL;
TDevice * Device = NULL; TDevice * Device = NULL;
char * DeviceName = NULL; char * DeviceName = NULL;
int DeviceID = 0;
char * DeviceAddr = NULL;
char * DeviceType = NULL; char * DeviceType = NULL;
// Load Device Types // Load Device Types
DeviceData = Config->GetChFirstChild( "DeviceTypes", true ); DeviceData = Config->GetChFirstChild( "DeviceTypes", true );
while (DeviceData) while (DeviceData)
{ {
DeviceName = (char*)DeviceData->GetName(); DeviceType = (char*)DeviceData->GetName();
Device = AddDeviceType( DeviceName ); Device = AddDeviceType( DeviceType );
if (Device) {
if (DeviceData->isString()) { if (DeviceData->isString()) {
if (JSONparse->ReadFromFile( DeviceName, DeviceData->GetStr() )) { // Contains file reference if (JSONparse->ReadFromFile( DeviceType, DeviceData->GetStr() )) { // Contains file reference
InitDeviceParams( Device, ConfigTypes->GetChild( DeviceName ) ); InitDeviceParams( Device, ConfigTypes->GetChild( DeviceType ) );
InitParamGroups( Device, ConfigTypes->GetChild( DeviceName ) ); InitParamGroups( Device, ConfigTypes->GetChild( DeviceType ) );
JSONparse->WriteToFile( DeviceName, DeviceData->GetStr() ); JSONparse->WriteToFile( DeviceType, DeviceData->GetStr() );
} }
else { else {
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Fail to load device type '%s' from file: '%s'", if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Fail to load device type '%s' from file: '%s'",
ProcessName, Name, DeviceName, DeviceData->GetStr() ); ProcessName, Name, DeviceType, DeviceData->GetStr() );
} }
} }
else if (DeviceData->isObject()) { else if (DeviceData->isObject()) {
@@ -141,7 +145,8 @@ bool CDeviceCore::InitDevices( CDataMember * FunctionConfig )
} }
else { else {
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Invalid device type config for '%s'", if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Invalid device type config for '%s'",
ProcessName, Name, DeviceName ); ProcessName, Name, DeviceType );
}
} }
DeviceData = DeviceData->GetNextPeer(); DeviceData = DeviceData->GetNextPeer();
} }
@@ -151,12 +156,15 @@ bool CDeviceCore::InitDevices( CDataMember * FunctionConfig )
while (DeviceData) while (DeviceData)
{ {
DeviceName = (char*)DeviceData->GetName(); DeviceName = (char*)DeviceData->GetName();
DeviceType = (char*)DeviceData->GetChStr( "Type" ); DeviceID = DeviceData->GetChInt( "ID", 0 );
Device = AddDevice( DeviceName, DeviceType ); DeviceAddr = (char*)DeviceData->GetChStr( "Address", NULL );
DeviceType = (char*)DeviceData->GetChStr( "Type", NULL );
Device = AddDevice( DeviceName, DeviceType, DeviceID, DeviceAddr );
if (Device) {
InitDeviceParams( Device, DeviceData ); InitDeviceParams( Device, DeviceData );
InitParamGroups( Device, DeviceData ); InitParamGroups( Device, DeviceData );
}
DeviceData = DeviceData->GetNextPeer(); DeviceData = DeviceData->GetNextPeer();
} }
return true; return true;
@@ -179,23 +187,24 @@ bool CDeviceCore::InitDeviceParams( TDevice * Device, CDataMember * DeviceConfi
// Copy Template // Copy Template
Template = (Device->Template)? Device->Template->FirstParam : NULL; Template = (Device->Template)? Device->Template->FirstParam : NULL;
while (Template) { while (Template)
{
if ((Param = AddDeviceParam( Device, Template->Name, Template->DataType, Template->Len ))) if ((Param = AddDeviceParam( Device, Template->Name, Template->DataType, Template->Len )))
{ {
SetParamAccess( Param, Template->Read, Template->Write ); SetParamAccess( Param, Template->Read, Template->Write );
SetParamEvent( Param, (Template->EventChannel)? Template->EventChannel->Name : NULL, Template->EventInterval ); 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 ); UpdateUnsignedValue( Param, *((u_int16_t*)Template->Value), Template->Changed );
if (Template->SetChanged) if (Template->SetChanged)
SetUnsignedValue( Param, *((u_int16_t*)Template->Value), true ); 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 ); UpdateSignedValue( Param, *((int16_t*)Template->Value), Template->Changed );
if (Template->SetChanged) if (Template->SetChanged)
SetSignedValue( Param, *((int16_t*)Template->Value), true ); 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 ); UpdateFloatValue( Param, *((float*)Template->Value), Template->Changed );
if (Template->SetChanged) if (Template->SetChanged)
SetFloatValue( Param, *((float*)Template->Value), true ); SetFloatValue( Param, *((float*)Template->Value), true );
@@ -225,17 +234,17 @@ bool CDeviceCore::InitDeviceParams( TDevice * Device, CDataMember * DeviceConfi
SetParamEvent( Param, EventOut, EventInt ); SetParamEvent( Param, EventOut, EventInt );
if ((InitVal = ParamData->GetChild( "InitValue", false ))) { 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 ); UpdateUnsignedValue( Param, InitVal->GetInt(0), Read );
if (Write) if (Write)
SetUnsignedValue( Param, InitVal->GetInt(0), true ); 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 ); UpdateSignedValue( Param, InitVal->GetInt(0), Read );
if (Write) if (Write)
SetSignedValue( Param, InitVal->GetInt(0), true ); SetSignedValue( Param, InitVal->GetInt(0), true );
} }
else if (DataType == dtFloat32) { else if ((DataType == dtFloat32_L) || (DataType == dtFloat32_B)) {
UpdateFloatValue( Param, InitVal->GetFloat(0), Read ); UpdateFloatValue( Param, InitVal->GetFloat(0), Read );
if (Write) if (Write)
SetFloatValue( Param, InitVal->GetFloat(0), true ); SetFloatValue( Param, InitVal->GetFloat(0), true );
@@ -338,44 +347,51 @@ void CDeviceCore::SetWaitForReply()
// Set flag // Set flag
WaitingForReply = true; 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 // Check for Reply timeout
if (WaitingForReply && Timeout( PollWait, ReplyTimeout )) if (!WaitingForReply || !Timeout( PollWait, ReplyTimeout )) {
{ // No timeout
// Increment retries return false;
}
// Update flags
WaitingForReply = false;
InvalidReply = false;
PollRetry++; PollRetry++;
// Handle No Reply / Retry // Handle No Reply / Retry
if (PollRetry < MaxRetries) { if (PollRetry > MaxRetries)
// Log Event {
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Device '%s' timeout, retry [%d]", if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Device '%s' %s - Max retries",
ProcessName, Name, DeviceChannel->Name, ActiveDevice->Name, PollRetry ); ProcessName, Name, DeviceChannel->Name, ActiveDevice->Name,
} ((InvalidReply)? "invalid reply" : "timeout"), 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 // Set Device Offline
DeviceOnline( ActiveDevice, false ); DeviceOnline( ActiveDevice, false );
PollStep = TimeoutPollStep; PollRetry = 0;
}
// Reset flag - retry
WaitingForReply = false;
return true; return true;
} }
else
{ // Try again
// Reset retries if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Device '%s' %s, Retry %d/%d",
PollRetry = 0; ProcessName, Name, DeviceChannel->Name, ActiveDevice->Name,
((InvalidReply)? "invalid reply" : "timeout"), PollRetry, MaxRetries );
return false; return false;
} }
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
TDevice * CDeviceCore::AddDeviceType( const char * DeviceTypeName ) TDevice * CDeviceCore::AddDeviceType( const char * DeviceTypeName )
@@ -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 (!DeviceName || !*DeviceName || (DeviceAddress && !*DeviceAddress)) {
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Could not add device '%s' (%s)", ProcessName, Name, if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Could not add device '%s' - Invalid parameters, Tp:'%s' ID:%d, Addr:'%s'",
((DeviceName)? DeviceName : "[device]"), ((Type)? Type : "no type") ); ProcessName, Name, ((DeviceName)? DeviceName : "[no name]"), ((DeviceType)? DeviceType : "[none]"),
DeviceID, ((DeviceAddress)? DeviceAddress : "[none]") );
return NULL; return NULL;
} }
else if (*Device) {
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Device type '%s' (%s) already exists", ProcessName, Name, // Find device matching by any parameter
DeviceName, (((*Device)->Type)? (*Device)->Type : "no type") ); 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 { else {
*Device = new TDevice; *Device = new TDevice;
@@ -423,15 +457,23 @@ TDevice * CDeviceCore::AddDevice( const char * DeviceName, const char * Type )
(*Device)->Name = (char *)malloc( strlen( DeviceName )+1 ); (*Device)->Name = (char *)malloc( strlen( DeviceName )+1 );
strcpy( (*Device)->Name, DeviceName ); strcpy( (*Device)->Name, DeviceName );
if (Type && *Type) { (*Device)->ID = DeviceID;
(*Device)->Type = (char *)malloc( strlen( Type )+1 );
strcpy( (*Device)->Type, Type );
(*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, if (DeviceType && *DeviceType) {
DeviceName, ((Type)? Type : "no type"), (((*Device)->Template)? "*" : "") ); (*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; return *Device;
} }
@@ -451,6 +493,8 @@ bool CDeviceCore::DestroyDevice( TDevice ** Device )
// Destroy Device structure // Destroy Device structure
if ((*Device)->Name) if ((*Device)->Name)
free( (*Device)->Name ); free( (*Device)->Name );
if ((*Device)->Address)
free( (*Device)->Address );
if ((*Device)->Type) if ((*Device)->Type)
free( (*Device)->Type ); free( (*Device)->Type );
@@ -479,15 +523,17 @@ TDeviceParam * CDeviceCore::AddDeviceParam( TDevice * Device, const char * Param
if (!Param) { if (!Param) {
// Invalid device/param // Invalid device/param
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Param '%s/%s' cannot be created", ProcessName, Name, if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Could not add Param '%s/%s' - Invalid parameters, Tp:'%s'",
((!Device)? "[device]" : (Device->Name)? Device->Name : Device->Type), ProcessName, Name, ((!Device)? "[no name]" : (Device->Name)? Device->Name : Device->Type),
((!ParamName)? "[param]" : ParamName)); ((!ParamName)? "[no name]" : ParamName), DataTypeName[DataType]);
return NULL; return NULL;
} }
else if (*Param) { else if (*Param) {
// Parameter already exists // Parameter already exists
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Param '%s/%s' already exists", ProcessName, Name, if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Could not add Param '%s/%s' - Already exists",
((Device->Name)? Device->Name : Device->Type), ParamName, DataTypeName[DataType]); ProcessName, Name, ((Device->Name)? Device->Name : Device->Type),
ParamName, DataTypeName[DataType]);
return NULL;
} }
else { else {
// Create register // Create register
@@ -526,7 +572,8 @@ TDeviceParam * CDeviceCore::AddDeviceParam( TDevice * Device, const char * Param
(*Param)->SetLen = sizeof(int16_t); (*Param)->SetLen = sizeof(int16_t);
break; break;
case dtUnsigned32 : case dtUnsigned32_HL :
case dtUnsigned32_LH :
// Create Value pointer // Create Value pointer
(*Param)->Value = (u_int32_t*)malloc( sizeof(u_int32_t) ); (*Param)->Value = (u_int32_t*)malloc( sizeof(u_int32_t) );
*((u_int32_t*)(*Param)->Value) = 0; *((u_int32_t*)(*Param)->Value) = 0;
@@ -538,7 +585,8 @@ TDeviceParam * CDeviceCore::AddDeviceParam( TDevice * Device, const char * Param
(*Param)->SetLen = sizeof(u_int32_t); (*Param)->SetLen = sizeof(u_int32_t);
break; break;
case dtSigned32 : case dtSigned32_HL :
case dtSigned32_LH :
// Create Value pointer // Create Value pointer
(*Param)->Value = (int32_t*)malloc( sizeof(int32_t) ); (*Param)->Value = (int32_t*)malloc( sizeof(int32_t) );
*((int32_t*)(*Param)->Value) = 0; *((int32_t*)(*Param)->Value) = 0;
@@ -550,7 +598,8 @@ TDeviceParam * CDeviceCore::AddDeviceParam( TDevice * Device, const char * Param
(*Param)->SetLen = sizeof(int32_t); (*Param)->SetLen = sizeof(int32_t);
break; break;
case dtFloat32 : case dtFloat32_L :
case dtFloat32_B :
// Create Value pointer // Create Value pointer
(*Param)->Value = (float*)malloc( sizeof(float) ); (*Param)->Value = (float*)malloc( sizeof(float) );
*((float*)(*Param)->Value) = 0.0; *((float*)(*Param)->Value) = 0.0;
@@ -579,8 +628,9 @@ TDeviceParam * CDeviceCore::AddDeviceParam( TDevice * Device, const char * Param
} }
(*Param)->Changed = true; (*Param)->Changed = true;
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Added param '%s/%s' (%s)", ProcessName, Name, if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Added param '%s/%s', Tp:'%s'",
((Device->Name)? Device->Name : Device->Type), ParamName, DataTypeName[DataType]); ProcessName, Name, ((Device->Name)? Device->Name : Device->Type),
ParamName, DataTypeName[DataType]);
} }
return *Param; return *Param;
} }
@@ -621,8 +671,8 @@ TDeviceParamGroup * CDeviceCore::AddParamGroup( TDevice * Device, const char * G
TDeviceParamGroup ** ParamGroup = GetParamGroupPtr( Device, GroupName ); TDeviceParamGroup ** ParamGroup = GetParamGroupPtr( Device, GroupName );
if (!ParamGroup) { if (!ParamGroup) {
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Could not add param group '%s'", ProcessName, Name, if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Could not add param group '%s'",
((!Device)? "[device]" : (Device->Name)? Device->Name : Device->Type), ProcessName, Name, ((!Device)? "[device]" : (Device->Name)? Device->Name : Device->Type),
((GroupName)? GroupName : "[group]") ); ((GroupName)? GroupName : "[group]") );
return NULL; return NULL;
} }
@@ -683,19 +733,20 @@ TDeviceParamItem * CDeviceCore::AddParamItem( TDeviceParamGroup * Group, const c
if (!Item) { if (!Item) {
// Invalid group/param // Invalid group/param
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Param group item '%s/%s' cannot be created", ProcessName, Name, if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Param group item '%s/%s' cannot be created",
((!Group)? "[group]" : Group->Name), ((!ParamName)? "[param]" : ParamName)); ProcessName, Name, ((!Group)? "[group]" : Group->Name), ((!ParamName)? "[param]" : ParamName));
return NULL; return NULL;
} }
else if (*Item) { else if (*Item) {
// Item already exists // Item already exists
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Param Group item '%s/%s' already exists", ProcessName, Name, if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Param Group item '%s/%s' already exists",
Group->Name, ParamName ); ProcessName, Name, Group->Name, ParamName );
} }
else if (!(Param = GetDeviceParam( Group->Device, ParamName ))) { else if (!(Param = GetDeviceParam( Group->Device, ParamName ))) {
// Parameter does not exist // 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, if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Param '%s/%s' does not exists - Cannot add to Param group '%s'",
((Group->Device->Name)? Group->Device->Name : Group->Device->Type), ParamName, Group->Name ); ProcessName, Name, ((Group->Device->Name)? Group->Device->Name : Group->Device->Type),
ParamName, Group->Name );
} }
else { else {
*Item = new TDeviceParamItem; *Item = new TDeviceParamItem;
@@ -707,8 +758,9 @@ TDeviceParamItem * CDeviceCore::AddParamItem( TDeviceParamGroup * Group, const c
if (Param->Write) if (Param->Write)
Group->Write = true; Group->Write = true;
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Added param group item '%s/%s/%s'", ProcessName, Name, if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Added param group item '%s/%s/%s'",
((Group->Device->Name)? Group->Device->Name : Group->Device->Type), Group->Name, ParamName ); ProcessName, Name, ((Group->Device->Name)? Group->Device->Name : Group->Device->Type),
Group->Name, ParamName );
} }
return *Item; return *Item;
} }
@@ -792,7 +844,8 @@ bool CDeviceCore::UpdateUnsignedValue( TDeviceParam * Param, const u_int32_t Val
} }
break; break;
case dtUnsigned32 : case dtUnsigned32_HL :
case dtUnsigned32_LH :
if (Init || (*((u_int32_t*)Param->Value) != Value)) if (Init || (*((u_int32_t*)Param->Value) != Value))
{ {
// Set new value & mark change // Set new value & mark change
@@ -808,7 +861,9 @@ bool CDeviceCore::UpdateUnsignedValue( TDeviceParam * Param, const u_int32_t Val
} }
break; 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)) if (Init || (*((u_int32_t*)Param->Value) != Value))
{ {
// Set new value & mark change // Set new value & mark change
@@ -863,7 +918,8 @@ bool CDeviceCore::UpdateSignedValue( TDeviceParam * Param, const int32_t Value,
} }
break; break;
case dtSigned32 : case dtSigned32_HL :
case dtSigned32_LH :
if (Init || (*((int32_t*)Param->Value) != Value)) if (Init || (*((int32_t*)Param->Value) != Value))
{ {
// Set new value & mark change // Set new value & mark change
@@ -902,7 +958,8 @@ bool CDeviceCore::UpdateFloatValue( TDeviceParam * Param, const float Value, boo
switch (Param->DataType) switch (Param->DataType)
{ {
case dtFloat32 : case dtFloat32_L :
case dtFloat32_B :
if (Init || (*((float*)Param->Value) != Value)) if (Init || (*((float*)Param->Value) != Value))
{ {
// Set new value & mark change // Set new value & mark change
@@ -999,7 +1056,8 @@ bool CDeviceCore::SetUnsignedValue( TDeviceParam * Param, const u_int32_t Value,
} }
break; break;
case dtUnsigned32 : case dtUnsigned32_HL :
case dtUnsigned32_LH :
if (Force || (*((u_int32_t*)Param->SetValue) != Value)) if (Force || (*((u_int32_t*)Param->SetValue) != Value))
{ {
// Set new value // Set new value
@@ -1038,7 +1096,8 @@ bool CDeviceCore::SetSignedValue( TDeviceParam * Param, const int32_t Value, boo
} }
break; break;
case dtSigned32 : case dtSigned32_HL :
case dtSigned32_LH :
if (Force || (*((int32_t*)Param->SetValue) != Value)) if (Force || (*((int32_t*)Param->SetValue) != Value))
{ {
// Set new value // Set new value
@@ -1066,7 +1125,8 @@ bool CDeviceCore::SetFloatValue( TDeviceParam * Param, const float Value, bool F
switch (Param->DataType) switch (Param->DataType)
{ {
case dtFloat32 : case dtFloat32_L :
case dtFloat32_B :
if (Force || (*((float*)Param->SetValue) != Value)) if (Force || (*((float*)Param->SetValue) != Value))
{ {
// Set new value // Set new value
@@ -1147,18 +1207,21 @@ bool CDeviceCore::SetValue( TDeviceParam * Param, const char * Value, const int
switch (Param->DataType) switch (Param->DataType)
{ {
case dtUnsigned16 : case dtUnsigned16 :
case dtUnsigned32 : case dtUnsigned32_HL :
case dtUnsigned32_LH :
UnsignedVal = (u_int32_t)strtoul( ((UseTempStr)? TempStr : Value), NULL, 10 ); UnsignedVal = (u_int32_t)strtoul( ((UseTempStr)? TempStr : Value), NULL, 10 );
SetUnsignedValue( Param, UnsignedVal, Force ); SetUnsignedValue( Param, UnsignedVal, Force );
break; break;
case dtSigned16 : case dtSigned16 :
case dtSigned32 : case dtSigned32_HL :
case dtSigned32_LH :
SignedVal = (u_int32_t)strtol( ((UseTempStr)? TempStr : Value), NULL, 10 ); SignedVal = (u_int32_t)strtol( ((UseTempStr)? TempStr : Value), NULL, 10 );
SetUnsignedValue( Param, SignedVal, Force ); SetUnsignedValue( Param, SignedVal, Force );
break; break;
case dtFloat32 : case dtFloat32_L :
case dtFloat32_B :
FloatVal = (u_int32_t) strtof( ((UseTempStr)? TempStr : Value), NULL ); FloatVal = (u_int32_t) strtof( ((UseTempStr)? TempStr : Value), NULL );
SetUnsignedValue( Param, FloatVal, Force ); SetUnsignedValue( Param, FloatVal, Force );
break; break;
@@ -1189,7 +1252,8 @@ bool CDeviceCore::GetValue( TDeviceParam * Param, char * Value, int &Len )
sprintf( Value, "%u", (*((u_int16_t*)Param->Value)) ); sprintf( Value, "%u", (*((u_int16_t*)Param->Value)) );
break; break;
case dtUnsigned32 : case dtUnsigned32_HL :
case dtUnsigned32_LH :
sprintf( Value, "%u", (*((u_int32_t*)Param->Value)) ); sprintf( Value, "%u", (*((u_int32_t*)Param->Value)) );
break; break;
@@ -1197,11 +1261,13 @@ bool CDeviceCore::GetValue( TDeviceParam * Param, char * Value, int &Len )
sprintf( Value, "%d", (*((int16_t*)Param->Value)) ); sprintf( Value, "%d", (*((int16_t*)Param->Value)) );
break; break;
case dtSigned32 : case dtSigned32_HL :
case dtSigned32_LH :
sprintf( Value, "%d", (*((int32_t*)Param->Value)) ); sprintf( Value, "%d", (*((int32_t*)Param->Value)) );
break; break;
case dtFloat32 : case dtFloat32_L :
case dtFloat32_B :
sprintf( Value, "%f", (*((float*)Param->Value)) ); sprintf( Value, "%f", (*((float*)Param->Value)) );
break; break;
@@ -1333,7 +1399,7 @@ int CDeviceCore::HandleCommand( const char *ChannelName, const char * Data, cons
// Get device name // Get device name
GetCmdParam( NextParam, ParamName, &NextParam ); GetCmdParam( NextParam, ParamName, &NextParam );
if (!(Device = GetDevice( ParamName ))) { if (!(Device = GetDeviceByName( ParamName ))) {
// Unknown Parameters // Unknown Parameters
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown 'get' Device: '%s'", Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown 'get' Device: '%s'",
ProcessName, Name, ChannelName, ParamName ); ProcessName, Name, ChannelName, ParamName );
@@ -1382,7 +1448,7 @@ int CDeviceCore::HandleCommand( const char *ChannelName, const char * Data, cons
// Get Device name // Get Device name
GetCmdParam( NextParam, ParamName, &NextParam ); GetCmdParam( NextParam, ParamName, &NextParam );
if (!(Device = GetDevice( ParamName ))) { if (!(Device = GetDeviceByName( ParamName ))) {
// Unknown Parameters // Unknown Parameters
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown 'set' Device: '%s'", Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown 'set' Device: '%s'",
ProcessName, Name, ChannelName, ParamName ); ProcessName, Name, ChannelName, ParamName );
@@ -1437,7 +1503,7 @@ int CDeviceCore::HandleCommand( const char *ChannelName, const char * Data, cons
// Get Device name // Get Device name
GetCmdParam( NextParam, ParamName, &NextParam ); GetCmdParam( NextParam, ParamName, &NextParam );
if (!(Device = GetDevice( ParamName ))) { if (!(Device = GetDeviceByName( ParamName ))) {
// Unknown Parameters // Unknown Parameters
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown 'status' Device: '%s'", Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' - Unknown 'status' Device: '%s'",
ProcessName, Name, ChannelName, ParamName ); 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) ); sprintf( Message, "%s: %u\n", Param->Name, *((u_int16_t*)Param->Value) );
break; break;
case dtUnsigned32 : case dtUnsigned32_HL :
case dtUnsigned32_LH :
sprintf( Message, "%s: %u\n", Param->Name, *((u_int32_t*)Param->Value) ); sprintf( Message, "%s: %u\n", Param->Name, *((u_int32_t*)Param->Value) );
break; break;
@@ -1496,11 +1563,13 @@ bool CDeviceCore::EventOutput( TDeviceParam * Param, bool Force )
sprintf( Message, "%s: %d\n", Param->Name, *((int16_t*)Param->Value) ); sprintf( Message, "%s: %d\n", Param->Name, *((int16_t*)Param->Value) );
break; break;
case dtSigned32 : case dtSigned32_HL :
case dtSigned32_LH :
sprintf( Message, "%s: %d\n", Param->Name, *((int32_t*)Param->Value) ); sprintf( Message, "%s: %d\n", Param->Name, *((int32_t*)Param->Value) );
break; break;
case dtFloat32 : case dtFloat32_L :
case dtFloat32_B :
sprintf( Message, "%s: %f\n", Param->Name, *((float*)Param->Value) ); sprintf( Message, "%s: %f\n", Param->Name, *((float*)Param->Value) );
break; break;

View File

@@ -18,11 +18,13 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Enumerated types // 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 // Constants
const char DataTypeCount = 6; const char DataTypeCount = 10;
const char DataTypeName[][20] = { "None", "Unsigned16", "Signed16", "Unsigned32", "Signed32", "Float32", "String" }; 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 // Devices with are polled
struct SDevice { struct SDevice {
// Device definition // Device Identification
char * Name = NULL; char * Name = NULL;
int ID = 0;
char * Address = NULL;
// Device Type
char * Type = NULL; char * Type = NULL;
TDevice * Template = NULL; TDevice * Template = NULL;
@@ -131,6 +137,7 @@ protected:
// Reply // Reply
bool WaitingForReply; // Command sent, waiting for reply bool WaitingForReply; // Command sent, waiting for reply
bool InvalidReply; // Invalid reply received
long ReplyTimeout; // Max waiting time for reply long ReplyTimeout; // Max waiting time for reply
// Retry // Retry
@@ -154,17 +161,41 @@ protected:
} }
// Find Devices // Find Devices
inline TDevice * GetDevice( const char * Name ) { inline TDevice * GetDeviceByName( const char * pName ) {
TDevice ** Device = GetDevicePtr(Name); TDevice ** Device = GetDevicePtrByName( pName );
return (Device)? *Device : NULL; return (Device)? *Device : NULL;
} }
inline TDevice ** GetDevicePtr( const char * Name ) { inline TDevice ** GetDevicePtrByName( const char * pName ) {
if (!Name || !*Name) return NULL; if (!pName || !*pName) return NULL;
TDevice ** Device = &FirstDevice; TDevice ** Device = &FirstDevice;
while (*Device && strcasecmp( (*Device)->Name, Name )) while (*Device && strcasecmp( (*Device)->Name, pName ))
Device = &((*Device)->Next); Device = &((*Device)->Next);
return Device; 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 ) { inline TDevice * GetNextTypeDevice( const char * Type, TDevice * PrevDevice = NULL ) {
TDevice * Device = (PrevDevice)? PrevDevice->Next : FirstDevice; TDevice * Device = (PrevDevice)? PrevDevice->Next : FirstDevice;
while (Device && ((!Type && Device->Type) || (Type && (!Device->Type || strcasecmp( Type, Device->Type ))))) while (Device && ((!Type && Device->Type) || (Type && (!Device->Type || strcasecmp( Type, Device->Type )))))
@@ -264,7 +295,8 @@ protected:
// Handle Reply Timing // Handle Reply Timing
virtual void SetWaitForReply(); virtual void SetWaitForReply();
virtual bool CheckReplyTimeout( int TimeoutPollStep ); virtual void ValidReplyReceived();
virtual bool CheckReplyTimeout();
public: public:
// Life cycle // Life cycle
@@ -292,9 +324,9 @@ public:
} }
// Manage Devices // 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 ) { inline bool DestroyDevice( const char * DeviceName ) {
TDevice ** Device = GetDevicePtr(DeviceName); TDevice ** Device = GetDevicePtrByName(DeviceName);
return (Device)? DestroyDevice( Device ) : false; return (Device)? DestroyDevice( Device ) : false;
} }
@@ -335,7 +367,6 @@ public:
return SetStringValue( Param, Value, strlen(Value), Force ); return SetStringValue( Param, Value, strlen(Value), Force );
}; };
// Handle Interface Commands // Handle Interface Commands
bool GetCmdParam( const char * Start, char * Param, char ** NextParam ); 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 );

View File

@@ -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; TChannelLink * OutChannel = NULL;
int TempLen = 0; int TempLen = 0;
@@ -375,7 +375,7 @@ int CFunctionCore::Output( const TChannel * Channel, const char * Data, int Len
} }
// Log event // 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 ); ProcessName, Name, Channel->Name );
// Pass output to all linked inputs // Pass output to all linked inputs

View File

@@ -83,7 +83,7 @@ protected:
} }
// Data Input/Output // 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 ); virtual bool PullInput( TChannel * Channel );
public: public:

View File

@@ -2340,19 +2340,19 @@ int CSelectableCore::Input( const char * ChannelName, const char * Data, int Len
// Get Channel // Get Channel
if (!(Channel = GetChannel( ChannelName ))) { if (!(Channel = GetChannel( ChannelName ))) {
// Channel not found // 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 ); ProcessName, Name, ChannelName );
return 0; return 0;
} }
else if (!Channel->InputEnabled) { else if (!Channel->InputEnabled) {
// Channel disabled // 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 ); ProcessName, Name, ChannelName );
return 0; return 0;
} }
// Log event // 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 ); ProcessName, Name, ChannelName );
// Find Linked handle // Find Linked handle
@@ -2371,7 +2371,7 @@ int CSelectableCore::Input( const char * ChannelName, const char * Data, int Len
if (!HandleCount) { if (!HandleCount) {
// Handle not found // 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 ); ProcessName, Name, ChannelName );
return 0; return 0;
} }