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:
257
DeviceCore.cpp
257
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,24 +116,27 @@ 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 (Device) {
|
||||
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 (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, DeviceName, DeviceData->GetStr() );
|
||||
ProcessName, Name, DeviceType, DeviceData->GetStr() );
|
||||
}
|
||||
}
|
||||
else if (DeviceData->isObject()) {
|
||||
@@ -141,7 +145,8 @@ bool CDeviceCore::InitDevices( CDataMember * FunctionConfig )
|
||||
}
|
||||
else {
|
||||
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Invalid device type config for '%s'",
|
||||
ProcessName, Name, DeviceName );
|
||||
ProcessName, Name, DeviceType );
|
||||
}
|
||||
}
|
||||
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 );
|
||||
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 ))
|
||||
{
|
||||
// Increment retries
|
||||
if (!WaitingForReply || !Timeout( PollWait, ReplyTimeout )) {
|
||||
// No timeout
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update flags
|
||||
WaitingForReply = false;
|
||||
InvalidReply = false;
|
||||
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 );
|
||||
if (PollRetry > MaxRetries)
|
||||
{
|
||||
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 );
|
||||
|
||||
// Set Device Offline
|
||||
DeviceOnline( ActiveDevice, false );
|
||||
PollStep = TimeoutPollStep;
|
||||
}
|
||||
|
||||
// Reset flag - retry
|
||||
WaitingForReply = false;
|
||||
PollRetry = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset retries
|
||||
PollRetry = 0;
|
||||
|
||||
// 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;
|
||||
|
||||
|
||||
57
DeviceCore.h
57
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,7 +367,6 @@ 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 );
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user