/* * DeviceCore.h * * Created on: 18 May 2016 * Author: wentzelc */ #ifndef REDACORE_DEVICECORE_H_ #define REDACORE_DEVICECORE_H_ // Standard C/C++ Libraries /* none */ // redA Libraries #include "JSONparseCore.h" #include "FunctionCore.h" //--------------------------------------------------------------------------- // 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; 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 typedef struct SDevice TDevice; typedef struct SDeviceParam TDeviceParam; typedef struct SDeviceParamGroup TDeviceParamGroup; // Parameter group, e.g. used with polling parameters typedef struct SDeviceParamItem TDeviceParamItem; // Placeholder parameters in Parameter groups //--------------------------------------------------------------------------- // Devices with are polled struct SDevice { // Device Identification char * Name = NULL; int ID = 0; char * Address = NULL; char * DataPath = NULL; CDataMember * DataNode = NULL; // Device Type char * Type = NULL; TDevice * Template = NULL; // Device status bool Online = false; // Device parameters TDeviceParam * FirstParam = NULL; TDeviceParamGroup * FirstParamGroup = NULL; // Device peer list TDevice * Next = NULL; }; // Data parameters of devices struct SDeviceParam { // Parameter definition char * Name = NULL; EDeviceDataType DataType = dtNone; TDevice * Device = Device; // Data Path char * DataPath = NULL; CDataMember * DataNode = NULL; // Last value (received from device) void * Value = NULL; int Len = 0; bool Changed = false; // Polling/Event parameters bool Read = false; TChannel * EventChannel = NULL; long EventInterval = 0; timeval EventTimeout; // Value to on device bool Write = false; void * SetValue = NULL; int SetLen = 0; bool SetChanged = false; // Parameter peer list TDeviceParam * Next = NULL; }; // Parameters groups - used where parameters are read/written as a groug struct SDeviceParamGroup { char * Name = NULL; TDevice * Device = NULL; TDeviceParamItem * FirstParam = NULL; bool Read = false; bool Write = false; TDeviceParamGroup * NextGroup = NULL; }; struct SDeviceParamItem { TDeviceParam * Param = NULL; TDeviceParamItem * NextItem = NULL; }; //--------------------------------------------------------------------------- // Function Constructor List #define TYPE_DEVICE "Device" //CFunctionCore * NewDeviceCore( const char * Name ); //--------------------------------------------------------------------------- class CDeviceCore : public CFunctionCore { protected: // Configuration CDataMember * ConfigTypes = NULL; CDataMember * ValueTree = NULL; CJSONparse * JSONparse = NULL; bool DeviceInit = false; // Initialise device on start // Devices & Type TDevice * FirstDeviceType = NULL; TDevice * FirstDevice = NULL; TDevice * ActiveDevice = NULL; // Standard channels TChannel * DeviceChannel = NULL; TChannel * CmdChannel = NULL; TChannel * EventChannel = NULL; // Poll int PollCycle = 0; // Device Polling state, e.g. Init, Connect, Run, Disonnect, Shutdown int PollStep = 0; // Position in polling sequence timeval PollWait = {0,0}; // Time at which last poll was done long PollInterval = 250; // Minimum delay between polls // Reply bool WaitingForReply = false; // Command sent, waiting for reply bool InvalidReply = false; // Invalid reply received long DefReplyTimeout = 500; // Default Max waiting time for reply long ReplyTimeout = 500; // Max waiting time for reply // Retry 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 ); // Find Device Types inline TDevice * GetDeviceType( const char * TypeName ) { TDevice ** DeviceType = GetDeviceTypePtr( TypeName ); return (DeviceType)? *DeviceType : NULL; } inline TDevice ** GetDeviceTypePtr( const char * TypeName ) { if (!TypeName || !*TypeName) return NULL; TDevice ** DeviceType = &FirstDeviceType; while (*DeviceType && strcasecmp( (*DeviceType)->Type, TypeName )) DeviceType = &((*DeviceType)->Next); return DeviceType; } // Find Devices inline TDevice * GetDeviceByName( const char * pName ) { TDevice ** Device = GetDevicePtrByName( pName ); return (Device)? *Device : NULL; } inline TDevice ** GetDevicePtrByName( const char * pName ) { if (!pName || !*pName) return NULL; TDevice ** Device = &FirstDevice; 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 ))))) Device = Device->Next; return Device; } inline TDevice * GetNextOnlineDevice( TDevice * PrevDevice = NULL ) { TDevice * Device = (PrevDevice)? PrevDevice->Next : FirstDevice; while (Device && !Device->Online) Device = Device->Next; return Device; } // Manage Params bool DestroyDeviceParam( TDeviceParam ** Param ); // Find Params inline TDeviceParam * GetDeviceParam( TDevice * Device, const char * pName ) { TDeviceParam ** Param = GetDeviceParamPtr(Device, pName); return (Param)? *Param : NULL; } inline TDeviceParam ** GetDeviceParamPtr( TDevice * Device, const char * pName ) { if (!Device || !pName || !*pName) return NULL; TDeviceParam ** Param = &(Device->FirstParam); while (*Param && strcasecmp( (*Param)->Name, pName )) Param = &((*Param)->Next); return Param; } inline TDeviceParam * GetNextReadParam( TDevice * Device, TDeviceParam * LastParam = NULL ) { if (!Device) return NULL; TDeviceParam * Param = (LastParam)? LastParam->Next : Device->FirstParam; while (Param && (!Param->Read)) Param = Param->Next; return Param; } inline TDeviceParam * GetNextChangedParam( TDevice * Device, TDeviceParam * LastParam = NULL ) { if (!Device) return NULL; TDeviceParam * Param = (LastParam)? LastParam->Next : Device->FirstParam; while (Param && (!Param->Changed)) Param = Param->Next; return Param; } inline TDeviceParam * GetNextSetChangedParam( TDevice * Device, TDeviceParam * LastParam = NULL ) { if (!Device) return NULL; TDeviceParam * Param = (LastParam)? LastParam->Next : Device->FirstParam; while (Param && (!Param->SetChanged)) Param = Param->Next; return Param; } // Manage Param Groups bool DestroyParamGroup( TDeviceParamGroup ** Group ); bool DestroyParamItem( TDeviceParamItem ** Item ); // Find Param Groups inline TDeviceParamGroup * GetParamGroup( TDevice * Device, const char * GroupName ) { TDeviceParamGroup ** Group = GetParamGroupPtr( Device, GroupName ); return (Group)? *Group : NULL; } inline TDeviceParamGroup ** GetParamGroupPtr( TDevice * Device, const char * GroupName ) { if (!Device || !GroupName || !*GroupName) return NULL; TDeviceParamGroup ** Group = &(Device->FirstParamGroup); while (*Group && strcasecmp( (*Group)->Name, GroupName )) Group = &((*Group)->NextGroup); return Group; } inline TDeviceParamGroup * GetNextParamGroup( TDevice * Device, TDeviceParamGroup * LastParamGroup = NULL ) { if (!Device) return NULL; TDeviceParamGroup * ParamGroup = (LastParamGroup)? LastParamGroup->NextGroup : Device->FirstParamGroup; return ParamGroup; } // Find Param Groups Items inline TDeviceParamItem * GetParamItem( TDeviceParamGroup * Group, const char * ParamName ) { TDeviceParamItem ** Item = GetParamItemPtr( Group, ParamName ); return (Item)? *Item : NULL; } inline TDeviceParamItem ** GetParamItemPtr( TDeviceParamGroup * Group, const char * ParamName ) { if (!Group || !ParamName || !*ParamName) return NULL; TDeviceParamItem ** Item = &Group->FirstParam; while (*Item && strcasecmp( (*Item)->Param->Name, ParamName )) Item = &((*Item)->NextItem); return Item; } // Tools inline EDeviceDataType GetDataType( const char * TypeName ) { int Type; for (Type = 0; Type < DataTypeCount; Type++) 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 ); // Generate events bool EventOutput( TDeviceParam * Param, bool Force ); bool TimedParamEvents(); // Manage device virtual bool DeviceOnline( TDevice * Device, bool Online ); // Handle Reply Timing virtual void SetWaitForReply( int CustomTimeout = -1 ); virtual void ValidReplyReceived(); virtual bool CheckReplyTimeout(); public: // Life cycle CDeviceCore( const char * pName, const char * pType = TYPE_DEVICE ); virtual ~CDeviceCore(); // Configuration virtual bool Init( CDataMember * FunctionConfig ); virtual bool InitDevices( CDataMember * FunctionConfig ); virtual bool InitDeviceParams( TDevice * Device, CDataMember * DeviceConfig, CDataMember * ParentNode ); virtual bool CopyTemplateParam( TDevice * Device, TDeviceParam * Template, CDataMember * ParentNode ); virtual bool CopyTemplateParamGroups( TDevice * Device ); virtual bool InitDeviceParam( TDevice * Device, CDataMember * ParamConfig, const char * ParentName, const char * ParentPath, CDataMember * ParentNode, TDeviceParamGroup * ParentParamGroup ); // Polling parameters bool SetPollParam( int pPollInterval ); bool SetReplyParam( int pReplyTimeout, int pMaxRetries ); bool SetDataPath( TDeviceParam * Param, const char * DataPath, CDataMember * DataNode ); bool SetParamAccess( TDeviceParam * Param, bool Read, bool Write ); bool SetParamEvent( TDeviceParam * Param, const char * ChannelName, long pEventInterval ); // Manage Devices Types TDevice * AddDeviceType( const char * DeviceTypeName, const char * DataPath ); inline bool DestroyDeviceType( const char * DeviceTypeName ) { TDevice ** DeviceType = GetDeviceTypePtr(DeviceTypeName); return (DeviceType)? DestroyDevice( DeviceType ) : false; } // Manage Devices TDevice * AddDevice( const char * DeviceName, const char * Type = NULL, const int ID = 0, const char * Address = NULL, const char * DataPath = NULL ); inline bool DestroyDevice( const char * DeviceName ) { TDevice ** Device = GetDevicePtrByName(DeviceName); return (Device)? DestroyDevice( Device ) : false; } // Manage Params TDeviceParam * AddDeviceParam( TDevice * Device, const char * ParamName, EDeviceDataType DataType, int ParamLen = 1 ); inline bool DestroyDeviceParam( TDevice * Device, const char * ParamName ) { TDeviceParam ** Param = GetDeviceParamPtr( Device, ParamName ); return (Param)? DestroyDeviceParam( Param ) : false; }; // Manage Param Groups TDeviceParamGroup * AddParamGroup( TDevice * Device, const char * GroupName ); inline bool DestroyParamGroup( TDevice * Device, const char * GroupName ) { TDeviceParamGroup ** Group = GetParamGroupPtr( Device, GroupName ); return (Group)? DestroyParamGroup( Group ) : false; }; TDeviceParamItem * AddParamItem( TDeviceParamGroup * Group, TDeviceParam * Param ); inline bool DestroyParamItem( TDevice * Device, TDeviceParamGroup * Group, const char * ParamName ) { TDeviceParamItem ** Item = GetParamItemPtr( Group, ParamName ); return (Item)? DestroyParamItem( Item ) : false; }; // Update/Init Param values bool UpdateUnsignedValue( TDeviceParam * Param, const u_int32_t Value, bool Init ); bool UpdateSignedValue( TDeviceParam * Param, const int32_t Value, bool Init ); bool UpdateFloatValue( TDeviceParam * Param, const float Value, bool Init ); bool UpdateStringValue( TDeviceParam * Param, const char * Value, const int Len, bool Init ); inline bool UpdateStringValue( TDeviceParam * Param, const char * Value, bool Init ) { return UpdateStringValue( Param, Value, strlen(Value), Init ); }; // Change Param Update instruction bool SetUnsignedValue( TDeviceParam * Param, const u_int32_t Value, bool Force ); bool SetSignedValue( TDeviceParam * Param, const int32_t Value, bool Force ); bool SetFloatValue( TDeviceParam * Param, const float Value, bool Force ); bool SetStringValue( TDeviceParam * Param, const char * Value, const int Len, bool Force ); inline bool SetStringValue( TDeviceParam * Param, const char * Value, bool Force ) { 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 * SourceRef, const char * Data, const int MaxLen ); // Command Text Interfaces bool SetValue( TDeviceParam * Param, const char * Value, const int Len, bool Force ); bool GetValue( TDeviceParam * Param, char * Value, int &Len ); }; //--------------------------------------------------------------------------- #endif /* REDACORE_DEVICECORE_H_ */