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;
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;

View File

@@ -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 );

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;
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

View File

@@ -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:

View File

@@ -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;
}