From df371d4f105eb7a5e37e6f7386d46ebe434bac8d Mon Sep 17 00:00:00 2001 From: Charl Wentzel Date: Mon, 15 Jul 2019 17:29:45 +0200 Subject: [PATCH] Important Update: - DeviceCore: - Allow different event output types: None, Simple or JSON - Add date & time to JSON events --- DeviceCore.cpp | 132 ++++++++++++++++++++++++++++++++++++++----------- DeviceCore.h | 18 ++++++- 2 files changed, 118 insertions(+), 32 deletions(-) diff --git a/DeviceCore.cpp b/DeviceCore.cpp index 47da2b4..17b635f 100644 --- a/DeviceCore.cpp +++ b/DeviceCore.cpp @@ -13,6 +13,7 @@ // redA Libraries #include "ApplicationCore.h" #include "DeviceCore.h" +#include "DateTimeCore.h" //--------------------------------------------------------------------------- @@ -35,6 +36,7 @@ CDeviceCore::CDeviceCore( const char * pName, const char * pType ) : CFunctionCo // Data Structures ConfigTypes = new CDataMember(); ValueTree = new CDataMember(); + EventData = new CDataMember(); JSONparse = new CJSONparse(); } //--------------------------------------------------------------------------- @@ -52,6 +54,8 @@ CDeviceCore::~CDeviceCore() delete ConfigTypes; if (ValueTree) delete ValueTree; + if (EventData) + delete EventData; } //--------------------------------------------------------------------------- @@ -61,6 +65,7 @@ bool CDeviceCore::Init( CDataMember * FunctionConfig ) CDataMember * PollConfig = NULL; int IntVal1; int IntVal2; + char * StrVal; // Call Previous load config if (!CFunctionCore::Init( FunctionConfig )) @@ -105,6 +110,13 @@ bool CDeviceCore::Init( CDataMember * FunctionConfig ) 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 if (DeviceInit) { InitDevices( FunctionConfig ); @@ -1764,54 +1776,114 @@ int CDeviceCore::HandleCommand( const char *ChannelName, const char * SourceRef, // Generate Event output bool CDeviceCore::EventOutput( TDeviceParam * Param, bool Force ) { - char Message[200]; + int EventLen = EventMsgLen; + CDataMember * Path = NULL; // Validate if (!Param || !(Param->EventChannel)) return false; + if (EventOutputType == et_None) + return false; // Check Timer or force if (Force || (Param->EventInterval && Timeout( Param->EventTimeout, Param->EventInterval )) ) { + // Create message // Post event - switch (Param->DataType) - { - case dtBool : - sprintf( Message, "%s: %u\n", Param->DataPath, *((bool*)Param->Value) ); - break; + if (true) { + // JSON output + EventData->Clear(); + EventData->SetChStr( "Type", "ParamEvent" ); + EventData->SetChStr( "Time", GetDateTimeStr() ); - case dtUnsigned16 : - sprintf( Message, "%s: %u\n", Param->DataPath, *((u_int16_t*)Param->Value) ); - break; + 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 ); - case dtUnsigned32_HL : - case dtUnsigned32_LH : - sprintf( Message, "%s: %u\n", Param->DataPath, *((u_int32_t*)Param->Value) ); - break; + switch (Param->DataType) { + case dtBool : EventData->SetChBool( "Value", *((bool*)Param->Value) ); + break; - case dtSigned16 : - sprintf( Message, "%s: %d\n", Param->DataPath, *((int16_t*)Param->Value) ); - break; + case dtUnsigned16 : EventData->SetChBool( "Value", *((u_int16_t*)Param->Value) ); + break; - case dtSigned32_HL : - case dtSigned32_LH : - sprintf( Message, "%s: %d\n", Param->DataPath, *((int32_t*)Param->Value) ); - break; + case dtUnsigned32_HL : + case dtUnsigned32_LH : EventData->SetChBool( "Value", *((u_int32_t*)Param->Value) ); + break; - case dtFloat32_L : - case dtFloat32_B : - sprintf( Message, "%s: %f\n", Param->DataPath, *((float*)Param->Value) ); - break; + case dtSigned16 : EventData->SetChBool( "Value", *((int16_t*)Param->Value) ); + break; - case dtString : - sprintf( Message, "%s: %s\n", Param->DataPath, (char*)Param->Value ); - break; + case dtSigned32_HL : + case dtSigned32_LH : EventData->SetChBool( "Value", *((int32_t*)Param->Value) ); + break; - default : - break; + case dtFloat32_L : + case dtFloat32_B : EventData->SetChBool( "Value", *((float*)Param->Value) ); + break; + + case dtString : EventData->SetChBool( "Value", (char*)Param->Value ); + break; + + default : EventData->SetChNull( "Value" ); + break; + } + JSONparse->SetBase( EventData ); + JSONparse->WriteToString( NULL, EventMsg, EventLen, 0 ); } - Output( Param->EventChannel, NULL, true, Message, strlen(Message) ); + 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 if (Param->EventInterval) { diff --git a/DeviceCore.h b/DeviceCore.h index 655db1c..2cfb8cc 100644 --- a/DeviceCore.h +++ b/DeviceCore.h @@ -20,12 +20,14 @@ // Enumerated types 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; - -// Constants const char DataTypeCount = 10; const char DataTypeName[][20] = { "None", "Boolean", "Unsigned16", "Signed16", "Unsigned32_HL", "Unsigned32_LH", "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 @@ -152,6 +154,12 @@ protected: int PollRetry = 0; // No of polling retries that has timed out 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 bool DestroyDevice( TDevice ** Device ); @@ -298,6 +306,12 @@ protected: if (!strcasecmp( TypeName, DataTypeName[Type])) break; 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 );