401 lines
16 KiB
C++
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_ */
|