Files
sicspsi/pardef.h
zolliker f16d738b4a improvements:
- added is_running to driveable ease objects
- ighdriv.c: try <maxtry> times when status reply failes
- ipsdriv.c: fix trainedTo parameter
- reduced SEA version of SICS
2021-09-16 12:35:06 +02:00

258 lines
11 KiB
C

/*---------------------------------------------------------------------------
pardef.h
my way to define and handle objects and its parameters
Markus Zolliker, March 2005
----------------------------------------------------------------------------
*/
#ifndef PARDEF_H
#define PARDEF_H
#include "sics.h"
#include "logger.h"
#include "hipadaba.h"
int ParPrintf(void *object, int iOut, const char *fmt, ...);
typedef enum { PAR_ALWAYS_READY, PAR_NOT_READY, PAR_NOW_READY } ReadyState;
typedef struct ParInfo {
struct ParInfo *next;
char *name;
Logger *log;
int saveIt; /* bool */
int saveLog; /* bool */
ReadyState state; /* enum ReadyState */
int sugarStatus; /* =1: sugar object made */
pHdb node; /* node for update */
} ParInfo;
#define PAR_LEVELS 8
#define PAR_NAN -999999.
#define PAR_LNAN -999999
typedef void (*ParDef) (void *);
typedef struct ParClass {
char *name;
size_t size;
int level;
struct ParClass *base[PAR_LEVELS];
} ParClass;
typedef struct ParData {
pObjectDescriptor desc; /* SICS object descriptor */
ParClass *class; /* class descriptor */
ParDef pardef;
char *creationCmd; /* the command to create this object */
char *name; /* object name */
time_t logTime; /* last logging time */
int logPending;
int period; /* logging interval */
ParInfo *infoList; /* list for additional info on parameters */
pICallBack pCall; /* sics callback function */
SConnection *conn; /* last connection with user or manager priv. */
int verbose; /* verbosity, mainly for tests */
pHdb node; /* node for update */
char *secop_module; /* secop module name, if enabled */
} ParData;
/*
Implementation of an object:
object data:
The first member of the objects data struct must be a plain ParData (not a pointer)
The ParData member may also be the first member of an nested struct, the only
condition is, that it is at offset 0, i.e. a cast to ParData is always valid.
typedef struct {
ParData p;
// object members:
float value;
char *text;
FooSpecialObject *obj;
} FooData;
a static class object of type ParClass has to be declared and initialized
with its name and the object data size:
static ParClass fooClass {"Foo", sizeof(FooData) }
at initialisation, or at least before it is used first, it has
to be initialized with
ParMakeClass(&fooClass, NULL);
(NULL as the second argument makes ParData to be the base class,
if more levels of inheritance are used, use the base class as argument)
parameter definition:
The parameters definition is within the pardef function, for example
void FooPardef(void *object) {
FooData *data = ParCast(&fooClass, object);
ParName("value"); ParFmt("%.3f"); ParFloat(&data->value, 0.0);
ParName("text"); ParList(NULL); ParStr(&data->text, "");
if (ParAction() == PAR_KILL) {
if (data->obj) {
FreeSpecialObject(data->obj);
data->obj = NULL;
}
}
}
The first line in FooPardef is a cast converting the anonymous object to
your data type. ParCast does some validity checks, which are strongly recommended.
The next two lines are parameters definitions. A parameter definition starts always
with ParName, followed by some options, and ends with the parameter type definition.
FooPardef is called for all operations on data, so do not insert long calculations
inside it. For special actions, code may be inserted for something like killing
members.
All char arguments in the following functions might be referred even after
the function returned. If they are not a constant, it is the callers responsibility
to make its contents valid whenever they are used.
*/
void ParName(char *name); /* name must not change during lifetime of the object,
normally it is a constant */
/*
Options (to be called before parameter type definitions):
*/
void ParFmt(char *fmt); /* format (float only) */
void ParAccess(int access); /* access rights (default usInternal = read only) */
void ParSave(int save); /* save on status file (0: do not svae, 1: save, 2: saved by driver
(default: 0 for ParAccess(usInternal), 1 for others) */
void ParEnum(char *list[]); /* automatic keyword to number conversion */
void ParList(char *group); /* ParList may be repeated with several group arguments,
to appear on a list <group> subcommand. Give NULL
for std list, "" for no list */
void ParTail(char *tail); /* comment to appear after list entry (e.g. units).
If ParList is not called, ParTail will force to appear
in standard list. */
void ParLogAs(char *name); /* switch log on and give sugar name (NULL for no logging) */
/*
Parameter type definitions:
select one out of these per parameter, with
a pointer to the corresponding object member as argument
*/
void ParFloat(float *value, float defValue);
void ParInt(int *value, int defValue);
void ParFixedStr(char *value, int maxsize, char *defValue); /* fixed size string */
void ParStr(char **value, char *defValue); /* dynamic string */
typedef int (*ParCommand) (void *object, void *userarg, int argc,
char *argv[]);
/* command function to be executed */
int ParCmd(ParCommand cmd, void *userarg); /* command, returns 0 when not executed
else return value from cmd, default access
is usUser */
/*
If code has to be executed for a specific to a parameter and and action,
ParActionIs (see below) may be used. Typical usage:
if (ParActionIs(PAR_SET) > 0) {
things to do when parameter has changed
}
A parameter definition finishes after these calls.
There are predefined actions which are all handled by this module:
*/
typedef enum {
PAR_NOOP, /* no operation */
PAR_INIT, /* initialize object (called during initialisation) */
PAR_SHOW, /* show single parameter (1) */
PAR_SET, /* set a single parameter (1) */
PAR_GET, /* get a single float parameter (1) */
PAR_LIST, /* list all or a group of parameters (2) */
PAR_LOG, /* log all parameters activated for logging (2) */
PAR_LOGSWITCH, /* (de)activate single parameter for logging (1) */
PAR_SAVE, /* save all parameters activated for saving (2) */
PAR_SAVESWITCH, /* (de)activate single parameter for saving (1) */
PAR_KILL, /* kill content (called before remove) */
PAR_UPDATE, /* update hipadaba node */
PAR_HDBSET /* set from hipadaba node */
} ParAct;
int ParActionIs(ParAct action);
/* to be called inside the pardef function.
returns 0, when the action is not active.
returns 1 or -1 when the action is active.
the return value -1 is used under following conditions:
- for actions marked with (1), when the name does not match
(for this case ParActionIs may be called between the call to ParName
for the parameter referred and before the next call to ParName)
- for actions marked with (2), when the parameter was not used
(for this case ParActionIs must be called after the parameter definition
for the parameter referred and before the next call to ParName)
*/
void ParStdDef(void); /* handle the standard parameters "verbose" and "driver" */
void *ParObject(void); /* get the current object (to be called by functions
called inside pardef, when the object is not in the argument
list */
void ParLogReady(ReadyState state); /* set ready state for log */
FILE *ParSaveFile(void); /* get the save-file name when action is PAR_SAVE */
char *ParGetValueArg(); /* get the set argument for floats and ints. If this function
is called, the caller is reponsible for assigning the value
to the object parameter */
/*
functions to be used outside pardef:
*/
void ParUpdateAll(void *object); /* update all hdb nodes */
int ParLog(void *object); /* log all parameters of this object, but only if not
already logged in the interval, returns >= 0 when done,
or < 0, when not done (execute PAR_LOG action) */
void ParKill(void *object); /* free the object (execute PAR_KILL action) */
void ParGetFloat(SConnection * con, void *object, char *name,
float *value);
/* get a float parameter (execute PAR_GET action) */
void *ParCast(ParClass * class, void *object);
/* returns object, if the object has type "class" or
inherits type "class", returns NULL otherwise */
void *ParCheck(ParClass * class, void *object);
/* dumps core when object has not or does not inherit "class" */
void *ParMakeClass(ParClass * class, ParClass * base);
/* initialize "class". base defines its base class or NULL
when ParData is its direct base class */
void *ParMake(SConnection * con, char *name, ParClass * class,
ParDef pardef, char *creationCmd);
/* make an object of class "class", and declare its
pardef function. Add it as command "name" to SICS,
and execute pardef with PAR_INIT action.
When creationCmd is not NULL, it is saved in order to
recreate the object.
The SICS system will execute:
- PAR_SHOW, PAR_SET, PAR_LIST, PAR_LOGSWITCH
from the corresponding command
- PAR_LOG after a PAR_SET action
- PAR_SAVE after a parameter change on any SICS command
- PAR_KILL on RemoveCommand */
char *ParArg2Str(int argc, char *argv[], char *res, int maxsize);
/* convert args to text. if res==NULL, the result is
allocated and maxsize is ignored */
void ParSaveConn(void *object, SConnection * con);
/* save connection for further use */
void ParInitPar(void *object, char *name, int logged);
/* inititalize dynamic parameter */
void ParKillPar(void *object, char *name);
/* delete dynamic parameter */
#endif