Files
redAcore/DeviceCore.h
2019-07-10 19:50:26 +02:00

401 lines
16 KiB
C++

/*
* 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;
// 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" };
//---------------------------------------------------------------------------
// 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
// 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;
}
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_ */