Important Update:

- DeviceCore:
  - Allow different event output types: None, Simple or JSON
  - Add date & time to JSON events
This commit is contained in:
Charl Wentzel
2019-07-15 17:29:45 +02:00
parent 91a7707fef
commit df371d4f10
2 changed files with 118 additions and 32 deletions

View File

@@ -13,6 +13,7 @@
// redA Libraries // redA Libraries
#include "ApplicationCore.h" #include "ApplicationCore.h"
#include "DeviceCore.h" #include "DeviceCore.h"
#include "DateTimeCore.h"
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -35,6 +36,7 @@ CDeviceCore::CDeviceCore( const char * pName, const char * pType ) : CFunctionCo
// Data Structures // Data Structures
ConfigTypes = new CDataMember(); ConfigTypes = new CDataMember();
ValueTree = new CDataMember(); ValueTree = new CDataMember();
EventData = new CDataMember();
JSONparse = new CJSONparse(); JSONparse = new CJSONparse();
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -52,6 +54,8 @@ CDeviceCore::~CDeviceCore()
delete ConfigTypes; delete ConfigTypes;
if (ValueTree) if (ValueTree)
delete ValueTree; delete ValueTree;
if (EventData)
delete EventData;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -61,6 +65,7 @@ bool CDeviceCore::Init( CDataMember * FunctionConfig )
CDataMember * PollConfig = NULL; CDataMember * PollConfig = NULL;
int IntVal1; int IntVal1;
int IntVal2; int IntVal2;
char * StrVal;
// Call Previous load config // Call Previous load config
if (!CFunctionCore::Init( FunctionConfig )) if (!CFunctionCore::Init( FunctionConfig ))
@@ -105,6 +110,13 @@ bool CDeviceCore::Init( CDataMember * FunctionConfig )
ProcessName, Name, PersistFile ); ProcessName, Name, PersistFile );
} }
// Event Output
StrVal = (char*)Config->GetChStr( "EventOutput", "None", true );
EventOutputType = GetEventType( StrVal );
Log->Message( LogLevel, dlMedium, "%s/%s: Event Output - Type:%s",
ProcessName, Name, EventTypeName[EventOutputType] );
// Update Devices -- may want to do it from derived class intead // Update Devices -- may want to do it from derived class intead
if (DeviceInit) { if (DeviceInit) {
InitDevices( FunctionConfig ); InitDevices( FunctionConfig );
@@ -1764,54 +1776,114 @@ int CDeviceCore::HandleCommand( const char *ChannelName, const char * SourceRef,
// Generate Event output // Generate Event output
bool CDeviceCore::EventOutput( TDeviceParam * Param, bool Force ) bool CDeviceCore::EventOutput( TDeviceParam * Param, bool Force )
{ {
char Message[200]; int EventLen = EventMsgLen;
CDataMember * Path = NULL;
// Validate // Validate
if (!Param || !(Param->EventChannel)) if (!Param || !(Param->EventChannel))
return false; return false;
if (EventOutputType == et_None)
return false;
// Check Timer or force // Check Timer or force
if (Force || if (Force ||
(Param->EventInterval && Timeout( Param->EventTimeout, Param->EventInterval )) ) (Param->EventInterval && Timeout( Param->EventTimeout, Param->EventInterval )) )
{ {
// Create message
// Post event // Post event
switch (Param->DataType) if (true) {
{ // JSON output
case dtBool : EventData->Clear();
sprintf( Message, "%s: %u\n", Param->DataPath, *((bool*)Param->Value) ); EventData->SetChStr( "Type", "ParamEvent" );
EventData->SetChStr( "Time", GetDateTimeStr() );
Path = EventData->GetChild( "Path", true );
Path->SetArray();
bool NewMember = true;
char * Start = NULL;
char * Pos = Param->DataPath;
while (true) {
if (!*Pos || (*Pos == '/')) {
NewMember = true;
if (Start)
Path->SetChStr( "[]", Start, Pos-Start );
if (!*Pos)
break;
}
else if (NewMember) {
NewMember = false;
Start = Pos;
}
Pos++;
}
EventData->SetChStr( "Device", Param->Device->Name );
EventData->SetChStr( "Param", Param->Name );
switch (Param->DataType) {
case dtBool : EventData->SetChBool( "Value", *((bool*)Param->Value) );
break; break;
case dtUnsigned16 : case dtUnsigned16 : EventData->SetChBool( "Value", *((u_int16_t*)Param->Value) );
sprintf( Message, "%s: %u\n", Param->DataPath, *((u_int16_t*)Param->Value) );
break; break;
case dtUnsigned32_HL : case dtUnsigned32_HL :
case dtUnsigned32_LH : case dtUnsigned32_LH : EventData->SetChBool( "Value", *((u_int32_t*)Param->Value) );
sprintf( Message, "%s: %u\n", Param->DataPath, *((u_int32_t*)Param->Value) );
break; break;
case dtSigned16 : case dtSigned16 : EventData->SetChBool( "Value", *((int16_t*)Param->Value) );
sprintf( Message, "%s: %d\n", Param->DataPath, *((int16_t*)Param->Value) );
break; break;
case dtSigned32_HL : case dtSigned32_HL :
case dtSigned32_LH : case dtSigned32_LH : EventData->SetChBool( "Value", *((int32_t*)Param->Value) );
sprintf( Message, "%s: %d\n", Param->DataPath, *((int32_t*)Param->Value) );
break; break;
case dtFloat32_L : case dtFloat32_L :
case dtFloat32_B : case dtFloat32_B : EventData->SetChBool( "Value", *((float*)Param->Value) );
sprintf( Message, "%s: %f\n", Param->DataPath, *((float*)Param->Value) );
break; break;
case dtString : case dtString : EventData->SetChBool( "Value", (char*)Param->Value );
sprintf( Message, "%s: %s\n", Param->DataPath, (char*)Param->Value );
break; break;
default : default : EventData->SetChNull( "Value" );
break; break;
} }
Output( Param->EventChannel, NULL, true, Message, strlen(Message) ); JSONparse->SetBase( EventData );
JSONparse->WriteToString( NULL, EventMsg, EventLen, 0 );
}
else {
switch (Param->DataType)
{
case dtBool : sprintf( EventMsg, "%s: %u\n", Param->DataPath, *((bool*)Param->Value) );
break;
case dtUnsigned16 : sprintf( EventMsg, "%s: %u\n", Param->DataPath, *((u_int16_t*)Param->Value) );
break;
case dtUnsigned32_HL :
case dtUnsigned32_LH : sprintf( EventMsg, "%s: %u\n", Param->DataPath, *((u_int32_t*)Param->Value) );
break;
case dtSigned16 : sprintf( EventMsg, "%s: %d\n", Param->DataPath, *((int16_t*)Param->Value) );
break;
case dtSigned32_HL :
case dtSigned32_LH : sprintf( EventMsg, "%s: %d\n", Param->DataPath, *((int32_t*)Param->Value) );
break;
case dtFloat32_L :
case dtFloat32_B : sprintf( EventMsg, "%s: %f\n", Param->DataPath, *((float*)Param->Value) );
break;
case dtString : sprintf( EventMsg, "%s: %s\n", Param->DataPath, (char*)Param->Value );
break;
default : sprintf( EventMsg, "%s:\n", Param->DataPath );
break;
}
}
// Send event
Output( Param->EventChannel, NULL, true, EventMsg, strlen(EventMsg) );
// Reset timer // Reset timer
if (Param->EventInterval) { if (Param->EventInterval) {

View File

@@ -20,12 +20,14 @@
// Enumerated types // Enumerated types
typedef enum { dtNone = 0, dtBool = 1, dtUnsigned16 = 2, dtSigned16 = 3, dtUnsigned32_HL = 4, dtUnsigned32_LH = 5, typedef enum { dtNone = 0, dtBool = 1, dtUnsigned16 = 2, dtSigned16 = 3, dtUnsigned32_HL = 4, dtUnsigned32_LH = 5,
dtSigned32_HL = 6, dtSigned32_LH = 7, dtFloat32_L = 8, dtFloat32_B = 9, dtString = 10 } EDeviceDataType; dtSigned32_HL = 6, dtSigned32_LH = 7, dtFloat32_L = 8, dtFloat32_B = 9, dtString = 10 } EDeviceDataType;
// Constants
const char DataTypeCount = 10; const char DataTypeCount = 10;
const char DataTypeName[][20] = { "None", "Boolean", "Unsigned16", "Signed16", "Unsigned32_HL", "Unsigned32_LH", const char DataTypeName[][20] = { "None", "Boolean", "Unsigned16", "Signed16", "Unsigned32_HL", "Unsigned32_LH",
"Signed32_HL", "Signed32_LH", "Float32_L", "Float32_B", "String" }; "Signed32_HL", "Signed32_LH", "Float32_L", "Float32_B", "String" };
typedef enum { et_None = 0, et_Simple = 1, et_JSON = 2 } EEventType;
const char EventTypeCount = 3;
const char EventTypeName[][10] = { "None", "Simple", "JSON" };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Structure prototypes // Structure prototypes
@@ -152,6 +154,12 @@ protected:
int PollRetry = 0; // No of polling retries that has timed out int PollRetry = 0; // No of polling retries that has timed out
int MaxRetries = 3; // Max allowed retries int MaxRetries = 3; // Max allowed retries
// Event output
EEventType EventOutputType = et_None;
CDataMember * EventData = NULL;
const int EventMsgLen = 1000;
char EventMsg[1000] = {0};
// Manage Devices // Manage Devices
bool DestroyDevice( TDevice ** Device ); bool DestroyDevice( TDevice ** Device );
@@ -298,6 +306,12 @@ protected:
if (!strcasecmp( TypeName, DataTypeName[Type])) break; if (!strcasecmp( TypeName, DataTypeName[Type])) break;
return (Type == DataTypeCount)? dtNone : (EDeviceDataType)Type; return (Type == DataTypeCount)? dtNone : (EDeviceDataType)Type;
} }
inline EEventType GetEventType( const char * TypeName ) {
int Type;
for (Type = 0; Type < EventTypeCount; Type++)
if (!strcasecmp( TypeName, EventTypeName[Type])) break;
return (Type == EventTypeCount)? et_None : (EEventType)Type;
}
bool CompareParamString( const char * ParamValue, const int ParamLen, const char * Value, const int Len ); bool CompareParamString( const char * ParamValue, const int ParamLen, const char * Value, const int Len );