- Improvements to Hipadaba

- New chopper driver for MARS Juelich chopper system
- New docbook based SANS manual


SKIPPED:
	psi/amorcomp.c
	psi/amordrive.h
	psi/amorset.c
	psi/amorset.h
	psi/amorset.tex
	psi/amorset.w
	psi/julcho.c
	psi/libpsi.a
	psi/make_gen
	psi/psi.c
This commit is contained in:
koennecke
2006-07-07 15:05:24 +00:00
parent 7d8ad7392c
commit e6ad9da6ad
16 changed files with 5724 additions and 77 deletions

View File

@ -99,7 +99,7 @@
if(argc < 2) if(argc < 2)
{ {
sprintf(pMessage, "ERROR: Ragument required for %s",argv[0]); sprintf(pMessage, "ERROR: argument required for %s",argv[0]);
SCWrite(pCon,pMessage,eError); SCWrite(pCon,pMessage,eError);
return 0; return 0;
} }
@ -149,7 +149,7 @@
return 0; return 0;
} }
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
static void KillChoco(void *pData) void KillChoco(void *pData)
{ {
pChoco self = NULL; pChoco self = NULL;

View File

@ -19,6 +19,7 @@
pCodri CHGetDriver(pChoco self); pCodri CHGetDriver(pChoco self);
int CHList(pChoco self, SConnection *pCon, char *name); int CHList(pChoco self, SConnection *pCon, char *name);
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
void KillChoco(void *pData);
int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData, int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]); int argc, char *argv[]);
int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData,

View File

@ -85,7 +85,7 @@ controller driver.
\item[SetPar] tries to set the parameter parname to the value \item[SetPar] tries to set the parameter parname to the value
fValue. The last is floating point which covers the frequent fValue. The last is floating point which covers the frequent
occurence of numeric values. occurence of numeric values.
\item[SetPar2] The same as SetPar but uses test string as input for \item[SetPar2] The same as SetPar but uses text string as input for
parameter setting. parameter setting.
\item[GetPar] retrieves the parameter parname formatted as text. The \item[GetPar] retrieves the parameter parname formatted as text. The
value is put into the buffer pBuffer. iBufLen is the maximum number of value is put into the buffer pBuffer. iBufLen is the maximum number of
@ -129,6 +129,7 @@ $\langle$chocoint {\footnotesize ?}$\rangle\equiv$
\mbox{}\verb@ pCodri CHGetDriver(pChoco self);@\\ \mbox{}\verb@ pCodri CHGetDriver(pChoco self);@\\
\mbox{}\verb@ int CHList(pChoco self, SConnection *pCon, char *name);@\\ \mbox{}\verb@ int CHList(pChoco self, SConnection *pCon, char *name);@\\
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\ \mbox{}\verb@/*------------------------------------------------------------------------*/@\\
\mbox{}\verb@ void KillChoco(void *pData);@\\
\mbox{}\verb@ int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\ \mbox{}\verb@ int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
\mbox{}\verb@ int argc, char *argv[]);@\\ \mbox{}\verb@ int argc, char *argv[]);@\\
\mbox{}\verb@ int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\ \mbox{}\verb@ int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
@ -366,8 +367,7 @@ $\langle$evada {\footnotesize ?}$\rangle\equiv$
\subsubsection{To Do} \subsubsection{To Do}
This scheme seems to be quite promising for handling many SICS This scheme seems to be quite promising for handling many SICS
objects. The following enhancements could be considered. Allow to set objects. The following enhancements could be considered. Allow to set
certain primitive parameters without a drivable interface. And add an certain primitive parameters without a drivable interface.
adapter for an environment variable in the controller.

View File

@ -72,7 +72,7 @@ controller driver.
\item[SetPar] tries to set the parameter parname to the value \item[SetPar] tries to set the parameter parname to the value
fValue. The last is floating point which covers the frequent fValue. The last is floating point which covers the frequent
occurence of numeric values. occurence of numeric values.
\item[SetPar2] The same as SetPar but uses test string as input for \item[SetPar2] The same as SetPar but uses text string as input for
parameter setting. parameter setting.
\item[GetPar] retrieves the parameter parname formatted as text. The \item[GetPar] retrieves the parameter parname formatted as text. The
value is put into the buffer pBuffer. iBufLen is the maximum number of value is put into the buffer pBuffer. iBufLen is the maximum number of
@ -111,6 +111,7 @@ includes:
pCodri CHGetDriver(pChoco self); pCodri CHGetDriver(pChoco self);
int CHList(pChoco self, SConnection *pCon, char *name); int CHList(pChoco self, SConnection *pCon, char *name);
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
void KillChoco(void *pData);
int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData, int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]); int argc, char *argv[]);
int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
@ -267,8 +268,7 @@ controller driver:
\subsubsection{To Do} \subsubsection{To Do}
This scheme seems to be quite promising for handling many SICS This scheme seems to be quite promising for handling many SICS
objects. The following enhancements could be considered. Allow to set objects. The following enhancements could be considered. Allow to set
certain primitive parameters without a drivable interface. And add an certain primitive parameters without a drivable interface.
adapter for an environment variable in the controller.

View File

@ -9,6 +9,9 @@
revised for use with tasker: Mark Koennecke, September 1997 revised for use with tasker: Mark Koennecke, September 1997
Locking added: Mark Koennecke, August 2002 Locking added: Mark Koennecke, August 2002
Refactored and instrumentation for instrument staticstics added.
Mark Koennecke, July 2006
Copyright: Copyright:
Labor fuer Neutronenstreuung Labor fuer Neutronenstreuung
@ -52,6 +55,7 @@
#include "devexec.h" #include "devexec.h"
#include "status.h" #include "status.h"
#include "lld.h" #include "lld.h"
#include "commandlog.h"
/* /*
#define DEBUG 1 #define DEBUG 1
@ -64,6 +68,13 @@
char *name; char *name;
commandContext comCon; commandContext comCon;
} DevEntry, *pDevEntry; } DevEntry, *pDevEntry;
/*------------------------------------------------------------------------*/
typedef struct {
pExeList self;
pDevEntry pDev;
pICountable pCountInt;
pIDrivable pDrivInt;
}checkContext, *pCheckContext;
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static pDevEntry CreateDevEntry(pObjectDescriptor pDes, void *pData, static pDevEntry CreateDevEntry(pObjectDescriptor pDes, void *pData,
float fVal, char *name) float fVal, char *name)
@ -402,7 +413,7 @@
/* Sometimes this gets called, though nothing is running. There are /* Sometimes this gets called, though nothing is running. There are
cases where this is feasible for maintainance, but in some cases it cases where this is feasible for maintainance, but in some cases it
is pure rubbish, because nothing runs. This will ne checkd here. is pure rubbish, because nothing runs. This will be checked here.
*/ */
if((self->pOwner == NULL) || (LLDcheck(self->iList) == LIST_EMPTY)) if((self->pOwner == NULL) || (LLDcheck(self->iList) == LIST_EMPTY))
{ {
@ -421,10 +432,7 @@
LLDnodeDataTo(self->iList,&pDev); LLDnodeDataTo(self->iList,&pDev);
if(pDev) if(pDev)
{ {
/* SCPushContext(self->pOwner, pDev->comCon.transID, pDev->comCon.deviceID);
SCSetContext(self->pOwner,pDev->cmdID,pDev->name);
*/
SCPushContext(self->pOwner, pDev->comCon.transID, pDev->comCon.deviceID);
pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData,DRIVEID); pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData,DRIVEID);
pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID); pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID);

5284
doc/user/sansdocbook.xml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -268,6 +268,7 @@ hdbValue makeHdbValue(int datatype, int length){
switch(datatype){ switch(datatype){
case HIPINTAR: case HIPINTAR:
case HIPINTVARAR:
val.arrayLength = length; val.arrayLength = length;
val.v.intArray = malloc(length*sizeof(long)); val.v.intArray = malloc(length*sizeof(long));
if(val.v.intArray != NULL){ if(val.v.intArray != NULL){
@ -275,6 +276,7 @@ hdbValue makeHdbValue(int datatype, int length){
} }
break; break;
case HIPFLOATAR: case HIPFLOATAR:
case HIPFLOATVARAR:
val.arrayLength = length; val.arrayLength = length;
val.v.floatArray = malloc(length*sizeof(double)); val.v.floatArray = malloc(length*sizeof(double));
if(val.v.floatArray != NULL){ if(val.v.floatArray != NULL){
@ -312,7 +314,7 @@ hdbValue MakeHdbText(char *initText){
return result; return result;
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
hdbValue MakeHdbIntArrray(int length, long *data){ hdbValue MakeHdbIntArray(int length, long *data){
hdbValue result; hdbValue result;
result.dataType = HIPINTAR; result.dataType = HIPINTAR;
@ -338,11 +340,13 @@ void ReleaseHdbValue(hdbValue *v){
} }
break; break;
case HIPINTAR: case HIPINTAR:
case HIPINTVARAR:
if(v->v.intArray != NULL){ if(v->v.intArray != NULL){
free(v->v.intArray); free(v->v.intArray);
} }
break; break;
case HIPFLOATAR: case HIPFLOATAR:
case HIPFLOATVARAR:
if(v->v.floatArray != NULL){ if(v->v.floatArray != NULL){
free(v->v.floatArray); free(v->v.floatArray);
} }
@ -382,6 +386,7 @@ int compareHdbValue(hdbValue v1, hdbValue v2){
} }
break; break;
case HIPINTAR: case HIPINTAR:
case HIPINTVARAR:
if(v1.arrayLength != v2.arrayLength){ if(v1.arrayLength != v2.arrayLength){
return 0; return 0;
} }
@ -393,6 +398,7 @@ int compareHdbValue(hdbValue v1, hdbValue v2){
return 1; return 1;
break; break;
case HIPFLOATAR: case HIPFLOATAR:
case HIPFLOATVARAR:
if(v1.arrayLength != v2.arrayLength){ if(v1.arrayLength != v2.arrayLength){
return 0; return 0;
} }
@ -430,6 +436,7 @@ pHdb MakeHipadabaNode(char *name, int datatype, int length){
pNew->value.dataType = datatype; pNew->value.dataType = datatype;
switch(datatype){ switch(datatype){
case HIPINTAR: case HIPINTAR:
case HIPINTVARAR:
pNew->value.arrayLength = length; pNew->value.arrayLength = length;
pNew->value.v.intArray = malloc(length*sizeof(long)); pNew->value.v.intArray = malloc(length*sizeof(long));
if(pNew->value.v.intArray == NULL){ if(pNew->value.v.intArray == NULL){
@ -438,6 +445,7 @@ pHdb MakeHipadabaNode(char *name, int datatype, int length){
memset(pNew->value.v.intArray,0,length*sizeof(long)); memset(pNew->value.v.intArray,0,length*sizeof(long));
break; break;
case HIPFLOATAR: case HIPFLOATAR:
case HIPFLOATVARAR:
pNew->value.arrayLength = length; pNew->value.arrayLength = length;
pNew->value.v.floatArray = malloc(length*sizeof(double)); pNew->value.v.floatArray = malloc(length*sizeof(double));
if(pNew->value.v.floatArray == NULL){ if(pNew->value.v.floatArray == NULL){
@ -498,13 +506,25 @@ int isHdbNodeValid(pHdb node){
} }
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
pHdb GetHipadabaNode(pHdb root, char *path){ pHdb GetHipadabaNode(pHdb root, char *puth){
pHdb resultNode = NULL; pHdb resultNode = NULL;
char *separator = NULL; char *separator = NULL;
char *path = NULL, *pathData;
/*
* I need to make a copy in order to get the path in writable memory.
* Otherwise we SEGFAULT in hdbTrim when this function is called with
* a string constant in puth
*/
pathData = strdup(puth);
path = pathData;
if(path == NULL){
return NULL;
}
path = hdbTrim(path); path = hdbTrim(path);
if(strcmp(path,"/") == 0 || strlen(path) == 0){ if(strcmp(path,"/") == 0 || strlen(path) == 0){
free(pathData);
return root; return root;
} }
@ -514,15 +534,20 @@ pHdb GetHipadabaNode(pHdb root, char *path){
separator = strchr(path,'/'); separator = strchr(path,'/');
if(separator == NULL){ if(separator == NULL){
return locateChild(root,path); resultNode = locateChild(root,path);
free(pathData);
return resultNode;
} else { } else {
*separator = '\0'; *separator = '\0';
resultNode = locateChild(root, path); resultNode = locateChild(root, path);
if(resultNode == NULL){ if(resultNode == NULL){
free(pathData);
return NULL; return NULL;
} else { } else {
separator++; separator++;
return GetHipadabaNode(resultNode,separator); resultNode = GetHipadabaNode(resultNode,separator);
free(pathData);
return resultNode;
} }
} }
} }
@ -715,6 +740,7 @@ int copyHdbValue(hdbValue *source, hdbValue *target){
target->v.text = strdup(source->v.text); target->v.text = strdup(source->v.text);
break; break;
case HIPINTAR: case HIPINTAR:
case HIPINTVARAR:
if(target->arrayLength != source->arrayLength){ if(target->arrayLength != source->arrayLength){
if(target->v.intArray != NULL){ if(target->v.intArray != NULL){
free(target->v.intArray); free(target->v.intArray);
@ -731,6 +757,7 @@ int copyHdbValue(hdbValue *source, hdbValue *target){
} }
break; break;
case HIPFLOATAR: case HIPFLOATAR:
case HIPFLOATVARAR:
if(target->arrayLength != source->arrayLength){ if(target->arrayLength != source->arrayLength){
if(target->v.floatArray != NULL){ if(target->v.floatArray != NULL){
free(target->v.floatArray); free(target->v.floatArray);

View File

@ -1,19 +1,21 @@
/** /**
* Hipadaba is a hierarchical database of parameters. Parameters can be of various types. * Hipadaba is a hierarchical database of parameters. Parameters can be of
* What happens when a parameter is being set, updated or read is largely determined * various types. What happens when a parameter is being set, updated or read
* through callbacks which can be registered on parameters. This can implement permission * is largely determined through callbacks which can be registered on
* checking, range checking, automatic notifications and whatever comes up. * parameters. This can implement permission checking, range checking,
* automatic notifications and whatever comes up.
* *
* There is some subtlety here between updating and setting a parameter. The issue is * There is some subtlety here between updating and setting a parameter. The
* that in instrument control there are two types of parameters: Instant program parameters * issue is that in instrument control there are two types of parameters:
* and external parameters like motors which are dependent on some possibly slow and * Instant program parameters and external parameters like motors which are
* inaccurate hardware. Let us consider the latter: Setting the parameter should do all * dependent on some possibly slow and inaccurate hardware. Let us consider
* necessary checks on the parameter and tell the hardware where to go. Some internal code * the latter: Setting the parameter should do all necessary checks on the
* may be watching the hardware; that code should use Update which justs sets a new value * parameter and tell the hardware where to go. Some internal code may be
* and invokes callbacks which notify interested parties about the new parameter value. * watching the hardware; that code should use Update which justs sets a new value
* For program parameters, a callback shall be installed which calls update directly * and invokes callbacks which notify interested parties about the new parameter
* after setting the parameter. Thus notification callbacks shall always be connected to the * value. For program parameters, a callback shall be installed which calls update
* update chain. * directly after setting the parameter. Thus notification callbacks shall always be
* connected to the update chain.
* *
* copyright: GPL * copyright: GPL
* *
@ -23,12 +25,14 @@
#define HIPADABA #define HIPADABA
/*------- datatypes */ /*------- datatypes */
#define HIPNONE -1 #define HIPNONE -1
#define HIPINT 0 #define HIPINT 0
#define HIPFLOAT 1 #define HIPFLOAT 1
#define HIPTEXT 2 #define HIPTEXT 2
#define HIPINTAR 3 #define HIPINTAR 3
#define HIPFLOATAR 4 #define HIPFLOATAR 4
#define HIPINTVARAR 5
#define HIPFLOATVARAR 6
/* -------- callback types */ /* -------- callback types */
#define HCBSET 0 #define HCBSET 0
#define HCBUPDATE 1 #define HCBUPDATE 1

4
lld.c
View File

@ -208,6 +208,10 @@ void LLDdelete( int List )
assert( (unsigned) List < ListCount ); assert( (unsigned) List < ListCount );
if(ListControl == NULL)
{
return;
}
Tmp = ListControl[ List ].first ; /* dummies are also deleted !!! */ Tmp = ListControl[ List ].first ; /* dummies are also deleted !!! */
while( NULL != Tmp ) /* still assuming last node has */ while( NULL != Tmp ) /* still assuming last node has */
{ /* a NULL next pointer ... */ { /* a NULL next pointer ... */

View File

@ -492,7 +492,7 @@ extern void KillPiPiezo(void *pData);
pM = (pMotor)self; pM = (pMotor)self;
MotorHalt(pM); /* MotorHalt(pM); */
if(pM->name) if(pM->name)
free(pM->name); free(pM->name);

View File

@ -35,6 +35,7 @@
#include "site.h" #include "site.h"
#include "tcldrivable.h" #include "tcldrivable.h"
#include "nserver.h" #include "nserver.h"
#include "sicshipadaba.h"
int ServerSetupInterrupt(int iPort, pNetRead pNet, pTaskMan pTasker); int ServerSetupInterrupt(int iPort, pNetRead pNet, pTaskMan pTasker);
/* /*
@ -396,6 +397,7 @@
KillFreeConnections(); KillFreeConnections();
killSICSHipadaba();
/* make fortify print his findings */ /* make fortify print his findings */
Fortify_DumpAllMemory(iFortifyScope); Fortify_DumpAllMemory(iFortifyScope);

10
obdes.c
View File

@ -44,6 +44,7 @@
#include "obdes.h" #include "obdes.h"
#include "conman.h" #include "conman.h"
#include "servlog.h" #include "servlog.h"
#include "hipadaba.h"
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static void *DefaultGetInterface(void *pData,int iID) static void *DefaultGetInterface(void *pData,int iID)
@ -67,6 +68,7 @@
} }
pRes->name = strdup(name); pRes->name = strdup(name);
pRes->pKeys = NULL; pRes->pKeys = NULL;
pRes->parNode = NULL;
pRes->SaveStatus = DefaultSave; pRes->SaveStatus = DefaultSave;
pRes->GetInterface = DefaultGetInterface; pRes->GetInterface = DefaultGetInterface;
return pRes; return pRes;
@ -77,6 +79,14 @@
assert(self); assert(self);
if(self->name) free(self->name); if(self->name) free(self->name);
if(self->pKeys) IFDeleteOptions(self->pKeys); if(self->pKeys) IFDeleteOptions(self->pKeys);
/*
* delate a parameter node only when not linked elsewhere
*/
if(self->parNode != NULL){
if(self->parNode->mama == NULL){
DeleteHipadabaNode(self->parNode);
}
}
free(self); free(self);
} }

View File

@ -23,12 +23,14 @@
#define SICSDESCRIPTOR #define SICSDESCRIPTOR
#include <stdio.h> #include <stdio.h>
#include <ifile.h> #include <ifile.h>
#include <hipadaba.h>
typedef struct { typedef struct {
char *name; char *name;
int (*SaveStatus)(void *self, char *name,FILE *fd); int (*SaveStatus)(void *self, char *name,FILE *fd);
void *(*GetInterface)(void *self, int iInterfaceID); void *(*GetInterface)(void *self, int iInterfaceID);
IPair *pKeys; IPair *pKeys;
pHdb parNode;
} ObjectDescriptor, *pObjectDescriptor; } ObjectDescriptor, *pObjectDescriptor;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/

2
ofac.c
View File

@ -376,7 +376,7 @@
RemoveCommand(pSics,"MakeLin2Ang"); RemoveCommand(pSics,"MakeLin2Ang");
RemoveCommand(pSics,"MakeSync"); RemoveCommand(pSics,"MakeSync");
RemoveCommand(pSics,"MakeHMControl"); RemoveCommand(pSics,"MakeHMControl");
/* RemoveCommand(pSics,"MakeRS232Controller"); */ RemoveCommand(pSics,"MakeRS232Controller");
RemoveCommand(pSics,"MakeMaxDetector"); RemoveCommand(pSics,"MakeMaxDetector");
RemoveCommand(pSics,"AntiColliderInstall"); RemoveCommand(pSics,"AntiColliderInstall");
RemoveCommand(pSics,"MakeGPIB"); RemoveCommand(pSics,"MakeGPIB");

View File

@ -13,6 +13,7 @@
#include <ctype.h> #include <ctype.h>
#include <sicshipadaba.h> #include <sicshipadaba.h>
#include <lld.h> #include <lld.h>
#include <stptok.h>
/*== there can be only hipadaba in SICS, some globals to care for that == */ /*== there can be only hipadaba in SICS, some globals to care for that == */
static pHdb root = NULL; static pHdb root = NULL;
@ -27,12 +28,22 @@ static int SICSCheckPermissionCallback(void *userData, void *callData, pHdb node
pCon = (SConnection *)callData; pCon = (SConnection *)callData;
testPriv = (int *)userData; testPriv = (int *)userData;
assert(pCon != NULL && testPriv != NULL); /*
* If pCon is NULL, then this is an internal call from some driver
* code where no permission check is necessary. However, when called
* through the hipadaba tree commands and other upper level code, the
* check will be honoured.
*/
if(pCon == NULL){
return 1;
}
assert(testPriv != NULL);
if(SCMatchRights(pCon,*testPriv) == 1){ if(SCMatchRights(pCon,*testPriv) == 1){
return 1; return 1;
} else { } else {
return 0; return SICSCBPERM;
} }
} }
/*--------------------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------------------*/
@ -60,10 +71,11 @@ static int SICSReadOnlyCallback(void *userData, void *callData, pHdb node,
SConnection *pCon = NULL; SConnection *pCon = NULL;
pCon = (SConnection *)callData; pCon = (SConnection *)callData;
assert(pCon != NULL);
SCWrite(pCon,"ERROR: parameter is READ-ONLY", eError); if(pCon != NULL){
return 0; SCWrite(pCon,"ERROR: parameter is READ-ONLY", eError);
}
return SICSCBRO;
} }
/*-------------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------------*/
static pHdbCallback MakeReadOnlyCallback(){ static pHdbCallback MakeReadOnlyCallback(){
@ -86,6 +98,31 @@ pHdbCallback MakeSICSDriveCallback(void *sicsObject){
return MakeHipadabaCallback(SICSDriveCallback, sicsObject,NULL,-1,-1); return MakeHipadabaCallback(SICSDriveCallback, sicsObject,NULL,-1,-1);
} }
/*---------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------*/
static int SICSReadDriveCallback(void *userData, void *callData, pHdb node,
hdbValue v){
SConnection *pCon = NULL;
pDummy dum = NULL;
pIDrivable pDriv = NULL;
float value;
pCon = (SConnection *)callData;
dum = (pDummy)userData;
assert(pCon != NULL && dum != NULL);
pDriv = dum->pDescriptor->GetInterface(dum,DRIVEID);
assert(pDriv != NULL);
if(pCon != NULL){
value = pDriv->GetValue(dum,pCon);
node->value.v.doubleValue = (double)value;
v.v.doubleValue = (double)value;
}
return 1;
}
/*--------------------------------------------------------------------------------------*/
pHdbCallback MakeSICSReadDriveCallback(void *sicsObject){
return MakeHipadabaCallback(SICSReadDriveCallback, sicsObject,NULL,-1,-1);
}
/*---------------------------------------------------------------------------------------*/
typedef struct { typedef struct {
SConnection *pCon; SConnection *pCon;
commandContext context; commandContext context;
@ -228,11 +265,144 @@ static int SICSScriptReadCallback(void *userData, void *callData, pHdb node,
} }
return status; return status;
} }
/*----------------------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
static pHdbCallback MakeSICSReadScriptCallback(char *script){ static pHdbCallback MakeSICSReadScriptCallback(char *script){
return MakeHipadabaCallback(SICSScriptReadCallback, strdup(script),free,-1,-1); return MakeHipadabaCallback(SICSScriptReadCallback, strdup(script),
free,-1,-1);
} }
/*============= Parameter Creation =======================================================*/ /*---------------------------------------------------------------------------*/
typedef struct {
int min;
int max;
}hdbIntRange, *pHdbIntRange;
/*---------------------------------------------------------------------------*/
static int SICSIntRangeCallback(void *userData, void *callData, pHdb node,
hdbValue v){
char buffer[256];
pHdbIntRange range = NULL;
SConnection *pCon = NULL;
int status = 1;
range = (pHdbIntRange)userData;
pCon = (SConnection *)callData;
assert(range != NULL);
if(v.v.intValue > range->max || v.v.intValue < range->min) {
status = SICSCBRANGE;
if(pCon != NULL){
snprintf(buffer,255,"ERROR: %d is not within permitted range: %d to %d",
(int)v.v.intValue, range->min, range->max);
SCWrite(pCon,buffer,eError);
}
}
return status;
}
/*---------------------------------------------------------------------------*/
pHdbCallback MakeIntRangeCallback(int min, int max){
pHdbIntRange range = NULL;
range = malloc(sizeof(hdbIntRange));
if(range == NULL){
return NULL;
}
range->min = min;
range->max = max;
return MakeHipadabaCallback(SICSIntRangeCallback, range,
free,-1,-1);
}
/*---------------------------------------------------------------------------*/
typedef struct {
double min;
double max;
}hdbFloatRange, *pHdbFloatRange;
/*---------------------------------------------------------------------------*/
static int SICSFloatRangeCallback(void *userData, void *callData, pHdb node,
hdbValue v){
char buffer[256];
pHdbFloatRange range = NULL;
SConnection *pCon = NULL;
int status = 1;
range = (pHdbFloatRange)userData;
pCon = (SConnection *)callData;
assert(range != NULL);
if(v.v.doubleValue > range->max || v.v.doubleValue < range->min) {
status = SICSCBRANGE;
if(pCon != NULL){
snprintf(buffer,255,"ERROR: %lf is not within permitted range: %lf to %lf",
v.v.doubleValue, range->min, range->max);
SCWrite(pCon,buffer,eError);
}
}
return status;
}
/*---------------------------------------------------------------------------*/
pHdbCallback MakeFloatRangeCallback(double min, double max){
pHdbFloatRange range = NULL;
range = malloc(sizeof(hdbFloatRange));
if(range == NULL){
return NULL;
}
range->min = min;
range->max = max;
return MakeHipadabaCallback(SICSFloatRangeCallback, range,
free,-1,-1);
}
/*--------------------------------------------------------------------------*/
static void killHdbValue(void *pData){
hdbValue *v = NULL;
v = (hdbValue *)pData;
if(v == NULL){
return;
}
ReleaseHdbValue(v);
free(v);
}
/*--------------------------------------------------------------------------*/
static int SICSIntFixedCallback(void *userData, void *callData, pHdb node,
hdbValue v){
hdbValue *allowed = NULL;
SConnection *pCon = NULL;
int i;
allowed = (hdbValue *)userData;
pCon = (SConnection *)callData;
assert(allowed != NULL && allowed->dataType == HIPINTAR);
for(i = 0; i < allowed->arrayLength; i++){
if(v.v.intValue == allowed->v.intArray[i]){
return 1;
}
}
if(pCon != NULL){
SCWrite(pCon,"ERROR: value is not in the list of allowed values",eError);
}
return SICSCBBADFIXED;
}
/*---------------------------------------------------------------------------*/
pHdbCallback MakeIntFixedCallback(long *data, int length){
pHdbCallback result = NULL;
hdbValue *v = NULL;
v = malloc(sizeof(hdbValue));
if(v == NULL){
return NULL;
}
v->dataType = HIPINTAR;
v->arrayLength = length;
v->v.intArray = malloc(length*sizeof(long));
if(v->v.intArray == NULL){
return NULL;
}
memcpy(v->v.intArray,data,length*sizeof(long));
return MakeHipadabaCallback(SICSIntFixedCallback, v,
killHdbValue,-1,-1);
}
/*============= Parameter Creation ===========================================*/
pHdb MakeSICSHdbPar(char *name, int priv, hdbValue v){ pHdb MakeSICSHdbPar(char *name, int priv, hdbValue v){
pHdb result = NULL; pHdb result = NULL;
pHdbCallback pHcb = NULL; pHdbCallback pHcb = NULL;
@ -283,10 +453,17 @@ pHdb MakeSICSHdbDriv(char *name, int priv, void *sicsObject, int dataType){
} }
AppendHipadabaCallback(result,HCBSET,pHcb); AppendHipadabaCallback(result,HCBSET,pHcb);
pHcb = MakeSICSReadDriveCallback(sicsObject);
if(pHcb == NULL){
DeleteHipadabaNode(result);
return NULL;
}
AppendHipadabaCallback(result,HCBREAD,pHcb);
return result; return result;
} }
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
pHdb MakeSICSHdbROPar(char *name, int priv, hdbValue v){ pHdb MakeSICSROPar(char *name, hdbValue v){
pHdb result = NULL; pHdb result = NULL;
pHdbCallback pHcb = NULL; pHdbCallback pHcb = NULL;
@ -296,7 +473,7 @@ pHdb MakeSICSHdbROPar(char *name, int priv, hdbValue v){
} }
copyHdbValue(&v,&result->value); copyHdbValue(&v,&result->value);
pHcb = MakeReadOnlyCallback(priv); pHcb = MakeReadOnlyCallback();
if(pHcb == NULL){ if(pHcb == NULL){
DeleteHipadabaNode(result); DeleteHipadabaNode(result);
return NULL; return NULL;
@ -498,6 +675,9 @@ int SICSHipadabaTask(void *pData){
if(self->iEnd == 1){ if(self->iEnd == 1){
return 0; return 0;
} }
if(LLDcheck(self->updateList) == LIST_EMPTY){
return 1;
}
memset(&old,0,sizeof(hdbValue)); memset(&old,0,sizeof(hdbValue));
memset(&newValue,0,sizeof(hdbValue)); memset(&newValue,0,sizeof(hdbValue));
@ -561,12 +741,14 @@ pDynString formatValue(hdbValue v){
DynStringCopy(result,v.v.text); DynStringCopy(result,v.v.text);
break; break;
case HIPINTAR: case HIPINTAR:
case HIPINTVARAR:
for(i = 0; i < v.arrayLength; i++){ for(i = 0; i < v.arrayLength; i++){
snprintf(number,30," %ld", v.v.intArray[i]); snprintf(number,30," %ld", v.v.intArray[i]);
DynStringConcat(result,number); DynStringConcat(result,number);
} }
break; break;
case HIPFLOATAR: case HIPFLOATAR:
case HIPFLOATVARAR:
for(i = 0; i < v.arrayLength; i++){ for(i = 0; i < v.arrayLength; i++){
snprintf(number,30," %12.4f", v.v.floatArray[i]); snprintf(number,30," %12.4f", v.v.floatArray[i]);
DynStringConcat(result,number); DynStringConcat(result,number);
@ -597,7 +779,39 @@ static char *getNextHdbNumber(char *pStart, char pNumber[80]){
pNumber[charCount] = '\0'; pNumber[charCount] = '\0';
return pStart; return pStart;
} }
/*---------------------------------------------------------------------------------*/
static int adjustDataLength(hdbValue *v, char *data){
char number[80];
int count = 0;
while(getNextHdbNumber(data,number) != NULL){
count++;
}
if(count != v->arrayLength){
v->arrayLength = count;
if(v->dataType == HIPINTVARAR){
if(v->v.intArray != NULL){
free(v->v.intArray);
}
v->v.intArray = malloc(count*sizeof(long));
if(v->v.intArray == NULL){
return 0;
}
memset(v->v.intArray,0,count*sizeof(long));
}
if(v->dataType == HIPFLOATVARAR){
if(v->v.floatArray != NULL){
free(v->v.floatArray);
}
v->v.floatArray = malloc(count*sizeof(double));
if(v->v.floatArray == NULL){
return 0;
}
memset(v->v.floatArray,0,count*sizeof(double));
}
}
return 1;
}
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
int readHdbValue(hdbValue *v, char *data, char *error, int errlen){ int readHdbValue(hdbValue *v, char *data, char *error, int errlen){
int i, status; int i, status;
@ -633,6 +847,11 @@ int readHdbValue(hdbValue *v, char *data, char *error, int errlen){
} }
v->v.text = strdup(data); v->v.text = strdup(data);
break; break;
case HIPINTVARAR:
if(!adjustDataLength(v,data)){
snprintf(error,errlen,"Out of memory allocating variable length data");
return 0;
}
case HIPINTAR: case HIPINTAR:
for(i = 0; i < v->arrayLength; i++){ for(i = 0; i < v->arrayLength; i++){
data = getNextHdbNumber(data,number); data = getNextHdbNumber(data,number);
@ -650,6 +869,11 @@ int readHdbValue(hdbValue *v, char *data, char *error, int errlen){
v->v.intArray[i] = lValue; v->v.intArray[i] = lValue;
} }
break; break;
case HIPFLOATVARAR:
if(!adjustDataLength(v,data)){
snprintf(error,errlen,"Out of memory allocating variable length data");
return 0;
}
case HIPFLOATAR: case HIPFLOATAR:
for(i = 0; i < v->arrayLength; i++){ for(i = 0; i < v->arrayLength; i++){
data = getNextHdbNumber(data,number); data = getNextHdbNumber(data,number);
@ -684,6 +908,8 @@ static char *hdbTypes[] = {"none",
"text", "text",
"intar", "intar",
"floatar", "floatar",
"intvarar",
"floatvarar",
NULL}; NULL};
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static int convertHdbType(char *text){ static int convertHdbType(char *text){
@ -729,9 +955,9 @@ static int MakeHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
*/ */
strtolower(argv[3]); strtolower(argv[3]);
type = convertHdbType(argv[3]); type = convertHdbType(argv[3]);
if(type >= 5){ if(type >= 7){
SCWrite(pCon, SCWrite(pCon,
"ERROR: invalid type requested: none, int, float, text, intar, floatar supported", "ERROR: invalid type requested: none, int, float, text, intar, floatar, intvarar, floatvarar supported",
eError); eError);
return 0; return 0;
} }
@ -800,9 +1026,9 @@ static int MakeHdbScriptNode(SConnection *pCon, SicsInterp *pSics, void *pData,
*/ */
strtolower(argv[4]); strtolower(argv[4]);
type = convertHdbType(argv[4]); type = convertHdbType(argv[4]);
if(type >= 5){ if(type >= 7){
SCWrite(pCon, SCWrite(pCon,
"ERROR: invalid type requested: none, int, float, text, intar, floatar supported", "ERROR: invalid type requested: none, int, float, text, intar, floatar, intvarar, floatvarar supported",
eError); eError);
return 0; return 0;
} }
@ -868,7 +1094,46 @@ static int DeleteHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
SCSendOK(pCon); SCSendOK(pCon);
return 1; return 1;
} }
/*------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static pHdb locateSICSNode(SicsInterp *pSics, SConnection *pCon, char *path){
pHdb result = NULL;
char *pPtr = NULL, sicsObj[128], error[256];
pDummy pDum = NULL;
CommandList *pCom = NULL;
if(strstr(path,"/sics/") != NULL){
pPtr = stptok(path,sicsObj,128,"/");
pPtr = stptok(pPtr,sicsObj,128,"/");
pPtr = stptok(pPtr,sicsObj,128,"/");
strtolower(sicsObj);
pCom = FindCommand(pSics,sicsObj);
if(pCom == NULL) {
snprintf(error,255,"ERROR: object %s not found",sicsObj);
SCWrite(pCon,error,eError);
return NULL;
}
pDum = (pDummy)pCom->pData;
if(pDum == NULL){
snprintf(error,255,"ERROR: object %s has no data",sicsObj);
SCWrite(pCon,error,eError);
return NULL;
}
if(pDum->pDescriptor->parNode == NULL){
snprintf(error,255,"ERROR: object %s does not use Hipadaba",sicsObj);
SCWrite(pCon,error,eError);
return NULL;
}
result = GetHipadabaNode(pDum->pDescriptor->parNode,pPtr);
} else {
result = GetHipadabaNode(root,path);
}
if(result == NULL){
snprintf(error,255,"ERROR: node %s NOT found",path);
SCWrite(pCon,error,eError);
}
return result;
}
/*---------------------------------------------------------------------------*/
static int SetHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, static int SetHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]){ int argc, char *argv[]){
pHdb targetNode = NULL; pHdb targetNode = NULL;
@ -887,10 +1152,8 @@ static int SetHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
return 0; return 0;
} }
targetNode = GetHipadabaNode(root,argv[1]); targetNode = locateSICSNode(pSics,pCon,argv[1]);
if(targetNode == NULL){ if(targetNode == NULL){
SCWrite(pCon,"ERROR: node to set not found!",
eError);
return 0; return 0;
} }
if(!cloneHdbValue(&targetNode->value,&newValue)){ if(!cloneHdbValue(&targetNode->value,&newValue)){
@ -936,10 +1199,8 @@ static int GetHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
} }
strncpy(oriPath,argv[1], 511); strncpy(oriPath,argv[1], 511);
targetNode = GetHipadabaNode(root,argv[1]); targetNode = locateSICSNode(pSics,pCon,argv[1]);
if(targetNode == NULL){ if(targetNode == NULL){
SCWrite(pCon,"ERROR: node to read not found!",
eError);
return 0; return 0;
} }
memset(&newValue,0,sizeof(hdbValue)); memset(&newValue,0,sizeof(hdbValue));
@ -1057,6 +1318,7 @@ static pDynString formatClientList(pHdb node){
DynStringConcat(result,current->value.v.text); DynStringConcat(result,current->value.v.text);
break; break;
case HIPINTAR: case HIPINTAR:
case HIPINTVARAR:
for(i = 0; i < length; i++){ for(i = 0; i < length; i++){
snprintf(number,50,"%ld",current->value.v.intArray[i]); snprintf(number,50,"%ld",current->value.v.intArray[i]);
DynStringConcat(result,number); DynStringConcat(result,number);
@ -1066,6 +1328,7 @@ static pDynString formatClientList(pHdb node){
} }
break; break;
case HIPFLOATAR: case HIPFLOATAR:
case HIPFLOATVARAR:
for(i = 0; i < length; i++){ for(i = 0; i < length; i++){
snprintf(number,50,"%lf",current->value.v.floatArray[i]); snprintf(number,50,"%lf",current->value.v.floatArray[i]);
DynStringConcat(result,number); DynStringConcat(result,number);
@ -1100,10 +1363,8 @@ static int ListHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
} }
} }
node = GetHipadabaNode(root,argv[pathArg]); node = locateSICSNode(pSics,pCon,argv[pathArg]);
if(node == NULL){ if(node == NULL){
SCWrite(pCon,"ERROR: node to list not found!",
eError);
return 0; return 0;
} }
@ -1136,10 +1397,8 @@ static int AutoNotifyHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
return 0; return 0;
} }
node = GetHipadabaNode(root,argv[1]); node = locateSICSNode(pSics,pCon,argv[1]);
if(node == NULL){ if(node == NULL){
SCWrite(pCon,"ERROR: node to add notify found!",
eError);
return 0; return 0;
} }
@ -1168,15 +1427,18 @@ static int RemoveHdbCallback(SConnection *pCon, SicsInterp *pSics, void *pData,
return 1; return 1;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void killSICSHipadaba(void *pData){ void killSICSHipadaba(){
DeleteHipadabaNode(root); if(root != NULL){
DeleteHipadabaNode(root);
}
root = NULL; root = NULL;
/** /**
* children have already been removed when killing the * children have already been removed when killing the
* main tree * main tree
*/ */
if(scriptUpdate > 0 && LLDcheck(scriptUpdate) != LIST_EMPTY){
LLDdelete(scriptUpdate); LLDdelete(scriptUpdate);
SCDeleteConnection(taskData.pCon); }
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int InstallSICSHipadaba(SConnection *pCon, SicsInterp *pSics, void *pData, int InstallSICSHipadaba(SConnection *pCon, SicsInterp *pSics, void *pData,
@ -1194,10 +1456,10 @@ int InstallSICSHipadaba(SConnection *pCon, SicsInterp *pSics, void *pData,
TaskRegister(pServ->pTasker, TaskRegister(pServ->pTasker,
SICSHipadabaTask, SICSHipadabaTask,
SICSHipadabaSignal, SICSHipadabaSignal,
killSICSHipadaba, NULL,
&taskData,1); &taskData,1);
AddCommand(pSics,"hmake", MakeHdbNode, killSICSHipadaba, NULL); AddCommand(pSics,"hmake", MakeHdbNode, NULL, NULL);
AddCommand(pSics,"hmakescript", MakeHdbScriptNode, NULL, NULL); AddCommand(pSics,"hmakescript", MakeHdbScriptNode, NULL, NULL);
AddCommand(pSics,"hdel", DeleteHdbNode, NULL, NULL); AddCommand(pSics,"hdel", DeleteHdbNode, NULL, NULL);
AddCommand(pSics,"hset", SetHdbNode, NULL, NULL); AddCommand(pSics,"hset", SetHdbNode, NULL, NULL);

View File

@ -12,6 +12,11 @@
#include <hipadaba.h> #include <hipadaba.h>
#include <sics.h> #include <sics.h>
#include <dynstring.h> #include <dynstring.h>
/*======================== callback error codes ===============================*/
#define SICSCBRO -607
#define SICSCBPERM -608
#define SICSCBRANGE -609
#define SICSCBBADFIXED -610
/*======================== data structure for automatic parameter update =======*/ /*======================== data structure for automatic parameter update =======*/
typedef struct { typedef struct {
SConnection *pCon; SConnection *pCon;
@ -40,6 +45,13 @@ pHdbCallback MakeSetUpdateCallback();
* starting a parameter driving. * starting a parameter driving.
*/ */
pHdbCallback MakeSICSDriveCallback(void *sicsObject); pHdbCallback MakeSICSDriveCallback(void *sicsObject);
/**
* make a callback which reads a SICS drivable object
* @param sicsObject The SICS drivable object to read.
* @return a suitably initialized callback structure for
* reading a drivable parameter
*/
pHdbCallback MakeSICSReadDriveCallback(void *sicsObject);
/** /**
* make a callback which enables automatically * make a callback which enables automatically
* notification of pCon on parameter updates. * notification of pCon on parameter updates.
@ -51,6 +63,33 @@ pHdbCallback MakeSICSDriveCallback(void *sicsObject);
* automatic notification. * automatic notification.
*/ */
pHdbCallback MakeNotifyCallback(SConnection *pCon, int id); pHdbCallback MakeNotifyCallback(SConnection *pCon, int id);
/**
* make a callback for checking if a parameter is within a given
* range of integers
* @param min The minimum value of the range
* @param max The maximum value of the range
* @return a suitably configured callback or NULL
* when out of memory
*/
pHdbCallback MakeIntRangeCallback(int min, int max);
/**
* make a callback for checking if a parameter is one out
* of a series of permitted integers
* @param data An array of permitted integers
* @param length The length of the data array.
* @return a suitably configured callback or NULL
* when out of memory
*/
pHdbCallback MakeIntFixedCallback(long *data, int length);
/**
* make a callback for checking if a parameter is within a given
* range of floats
* @param min The minimum value of the range
* @param max The maximum value of the range
* @return a suitably configured callback or NULL
* when out of memory
*/
pHdbCallback MakeFloatRangeCallback(double min, double max);
/*======================== parameter creation ===================================*/ /*======================== parameter creation ===================================*/
/** /**
* make a simple SICS hdb parameter. Setting it will call update immediately. Use * make a simple SICS hdb parameter. Setting it will call update immediately. Use
@ -171,5 +210,9 @@ int InstallSICSHipadaba(SConnection *pCon, SicsInterp *pSics, void *pData,
* @return The root node of the hipdaba * @return The root node of the hipdaba
*/ */
pHdb GetHipadabaRoot(); pHdb GetHipadabaRoot();
/**
* kill the SICS hierarchical database
* Only to be called when shutting down the SICServer
*/
void killSICSHipadaba(void);
#endif /*SICSHIPADABA_H_*/ #endif /*SICSHIPADABA_H_*/