- 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:
4
choco.c
4
choco.c
@ -99,7 +99,7 @@
|
||||
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
@ -149,7 +149,7 @@
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void KillChoco(void *pData)
|
||||
void KillChoco(void *pData)
|
||||
{
|
||||
pChoco self = NULL;
|
||||
|
||||
|
1
choco.h
1
choco.h
@ -19,6 +19,7 @@
|
||||
pCodri CHGetDriver(pChoco self);
|
||||
int CHList(pChoco self, SConnection *pCon, char *name);
|
||||
/*------------------------------------------------------------------------*/
|
||||
void KillChoco(void *pData);
|
||||
int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
|
@ -85,7 +85,7 @@ controller driver.
|
||||
\item[SetPar] tries to set the parameter parname to the value
|
||||
fValue. The last is floating point which covers the frequent
|
||||
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.
|
||||
\item[GetPar] retrieves the parameter parname formatted as text. The
|
||||
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@ int CHList(pChoco self, SConnection *pCon, char *name);@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ void KillChoco(void *pData);@\\
|
||||
\mbox{}\verb@ int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
@ -366,8 +367,7 @@ $\langle$evada {\footnotesize ?}$\rangle\equiv$
|
||||
\subsubsection{To Do}
|
||||
This scheme seems to be quite promising for handling many SICS
|
||||
objects. The following enhancements could be considered. Allow to set
|
||||
certain primitive parameters without a drivable interface. And add an
|
||||
adapter for an environment variable in the controller.
|
||||
certain primitive parameters without a drivable interface.
|
||||
|
||||
|
||||
|
||||
|
6
choco.w
6
choco.w
@ -72,7 +72,7 @@ controller driver.
|
||||
\item[SetPar] tries to set the parameter parname to the value
|
||||
fValue. The last is floating point which covers the frequent
|
||||
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.
|
||||
\item[GetPar] retrieves the parameter parname formatted as text. The
|
||||
value is put into the buffer pBuffer. iBufLen is the maximum number of
|
||||
@ -111,6 +111,7 @@ includes:
|
||||
pCodri CHGetDriver(pChoco self);
|
||||
int CHList(pChoco self, SConnection *pCon, char *name);
|
||||
/*------------------------------------------------------------------------*/
|
||||
void KillChoco(void *pData);
|
||||
int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
@ -267,8 +268,7 @@ controller driver:
|
||||
\subsubsection{To Do}
|
||||
This scheme seems to be quite promising for handling many SICS
|
||||
objects. The following enhancements could be considered. Allow to set
|
||||
certain primitive parameters without a drivable interface. And add an
|
||||
adapter for an environment variable in the controller.
|
||||
certain primitive parameters without a drivable interface.
|
||||
|
||||
|
||||
|
||||
|
18
devexec.c
18
devexec.c
@ -9,6 +9,9 @@
|
||||
revised for use with tasker: Mark Koennecke, September 1997
|
||||
Locking added: Mark Koennecke, August 2002
|
||||
|
||||
Refactored and instrumentation for instrument staticstics added.
|
||||
Mark Koennecke, July 2006
|
||||
|
||||
Copyright:
|
||||
|
||||
Labor fuer Neutronenstreuung
|
||||
@ -52,6 +55,7 @@
|
||||
#include "devexec.h"
|
||||
#include "status.h"
|
||||
#include "lld.h"
|
||||
#include "commandlog.h"
|
||||
|
||||
/*
|
||||
#define DEBUG 1
|
||||
@ -64,6 +68,13 @@
|
||||
char *name;
|
||||
commandContext comCon;
|
||||
} DevEntry, *pDevEntry;
|
||||
/*------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
pExeList self;
|
||||
pDevEntry pDev;
|
||||
pICountable pCountInt;
|
||||
pIDrivable pDrivInt;
|
||||
}checkContext, *pCheckContext;
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static pDevEntry CreateDevEntry(pObjectDescriptor pDes, void *pData,
|
||||
float fVal, char *name)
|
||||
@ -402,7 +413,7 @@
|
||||
|
||||
/* Sometimes this gets called, though nothing is running. There are
|
||||
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))
|
||||
{
|
||||
@ -421,10 +432,7 @@
|
||||
LLDnodeDataTo(self->iList,&pDev);
|
||||
if(pDev)
|
||||
{
|
||||
/*
|
||||
SCSetContext(self->pOwner,pDev->cmdID,pDev->name);
|
||||
*/
|
||||
SCPushContext(self->pOwner, pDev->comCon.transID, pDev->comCon.deviceID);
|
||||
SCPushContext(self->pOwner, pDev->comCon.transID, pDev->comCon.deviceID);
|
||||
|
||||
pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData,DRIVEID);
|
||||
pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID);
|
||||
|
5284
doc/user/sansdocbook.xml
Normal file
5284
doc/user/sansdocbook.xml
Normal file
File diff suppressed because it is too large
Load Diff
35
hipadaba.c
35
hipadaba.c
@ -268,6 +268,7 @@ hdbValue makeHdbValue(int datatype, int length){
|
||||
|
||||
switch(datatype){
|
||||
case HIPINTAR:
|
||||
case HIPINTVARAR:
|
||||
val.arrayLength = length;
|
||||
val.v.intArray = malloc(length*sizeof(long));
|
||||
if(val.v.intArray != NULL){
|
||||
@ -275,6 +276,7 @@ hdbValue makeHdbValue(int datatype, int length){
|
||||
}
|
||||
break;
|
||||
case HIPFLOATAR:
|
||||
case HIPFLOATVARAR:
|
||||
val.arrayLength = length;
|
||||
val.v.floatArray = malloc(length*sizeof(double));
|
||||
if(val.v.floatArray != NULL){
|
||||
@ -312,7 +314,7 @@ hdbValue MakeHdbText(char *initText){
|
||||
return result;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
hdbValue MakeHdbIntArrray(int length, long *data){
|
||||
hdbValue MakeHdbIntArray(int length, long *data){
|
||||
hdbValue result;
|
||||
|
||||
result.dataType = HIPINTAR;
|
||||
@ -338,11 +340,13 @@ void ReleaseHdbValue(hdbValue *v){
|
||||
}
|
||||
break;
|
||||
case HIPINTAR:
|
||||
case HIPINTVARAR:
|
||||
if(v->v.intArray != NULL){
|
||||
free(v->v.intArray);
|
||||
}
|
||||
break;
|
||||
case HIPFLOATAR:
|
||||
case HIPFLOATVARAR:
|
||||
if(v->v.floatArray != NULL){
|
||||
free(v->v.floatArray);
|
||||
}
|
||||
@ -382,6 +386,7 @@ int compareHdbValue(hdbValue v1, hdbValue v2){
|
||||
}
|
||||
break;
|
||||
case HIPINTAR:
|
||||
case HIPINTVARAR:
|
||||
if(v1.arrayLength != v2.arrayLength){
|
||||
return 0;
|
||||
}
|
||||
@ -393,6 +398,7 @@ int compareHdbValue(hdbValue v1, hdbValue v2){
|
||||
return 1;
|
||||
break;
|
||||
case HIPFLOATAR:
|
||||
case HIPFLOATVARAR:
|
||||
if(v1.arrayLength != v2.arrayLength){
|
||||
return 0;
|
||||
}
|
||||
@ -430,6 +436,7 @@ pHdb MakeHipadabaNode(char *name, int datatype, int length){
|
||||
pNew->value.dataType = datatype;
|
||||
switch(datatype){
|
||||
case HIPINTAR:
|
||||
case HIPINTVARAR:
|
||||
pNew->value.arrayLength = length;
|
||||
pNew->value.v.intArray = malloc(length*sizeof(long));
|
||||
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));
|
||||
break;
|
||||
case HIPFLOATAR:
|
||||
case HIPFLOATVARAR:
|
||||
pNew->value.arrayLength = length;
|
||||
pNew->value.v.floatArray = malloc(length*sizeof(double));
|
||||
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;
|
||||
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);
|
||||
|
||||
if(strcmp(path,"/") == 0 || strlen(path) == 0){
|
||||
free(pathData);
|
||||
return root;
|
||||
}
|
||||
|
||||
@ -514,15 +534,20 @@ pHdb GetHipadabaNode(pHdb root, char *path){
|
||||
|
||||
separator = strchr(path,'/');
|
||||
if(separator == NULL){
|
||||
return locateChild(root,path);
|
||||
resultNode = locateChild(root,path);
|
||||
free(pathData);
|
||||
return resultNode;
|
||||
} else {
|
||||
*separator = '\0';
|
||||
resultNode = locateChild(root, path);
|
||||
if(resultNode == NULL){
|
||||
free(pathData);
|
||||
return NULL;
|
||||
} else {
|
||||
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);
|
||||
break;
|
||||
case HIPINTAR:
|
||||
case HIPINTVARAR:
|
||||
if(target->arrayLength != source->arrayLength){
|
||||
if(target->v.intArray != NULL){
|
||||
free(target->v.intArray);
|
||||
@ -731,6 +757,7 @@ int copyHdbValue(hdbValue *source, hdbValue *target){
|
||||
}
|
||||
break;
|
||||
case HIPFLOATAR:
|
||||
case HIPFLOATVARAR:
|
||||
if(target->arrayLength != source->arrayLength){
|
||||
if(target->v.floatArray != NULL){
|
||||
free(target->v.floatArray);
|
||||
|
44
hipadaba.h
44
hipadaba.h
@ -1,19 +1,21 @@
|
||||
/**
|
||||
* Hipadaba is a hierarchical database of parameters. Parameters can be of various types.
|
||||
* What happens when a parameter is being set, updated or read is largely determined
|
||||
* through callbacks which can be registered on parameters. This can implement permission
|
||||
* checking, range checking, automatic notifications and whatever comes up.
|
||||
* Hipadaba is a hierarchical database of parameters. Parameters can be of
|
||||
* various types. What happens when a parameter is being set, updated or read
|
||||
* is largely determined through callbacks which can be registered on
|
||||
* 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
|
||||
* that in instrument control there are two types of parameters: Instant program parameters
|
||||
* and external parameters like motors which are dependent on some possibly slow and
|
||||
* inaccurate hardware. Let us consider the latter: Setting the parameter should do all
|
||||
* necessary checks on the parameter and tell the hardware where to go. Some internal code
|
||||
* may be watching the hardware; that code should use Update which justs sets a new value
|
||||
* and invokes callbacks which notify interested parties about the new parameter value.
|
||||
* For program parameters, a callback shall be installed which calls update directly
|
||||
* after setting the parameter. Thus notification callbacks shall always be connected to the
|
||||
* update chain.
|
||||
* There is some subtlety here between updating and setting a parameter. The
|
||||
* issue is that in instrument control there are two types of parameters:
|
||||
* Instant program parameters and external parameters like motors which are
|
||||
* dependent on some possibly slow and inaccurate hardware. Let us consider
|
||||
* the latter: Setting the parameter should do all necessary checks on the
|
||||
* parameter and tell the hardware where to go. Some internal code may be
|
||||
* watching the hardware; that code should use Update which justs sets a new value
|
||||
* and invokes callbacks which notify interested parties about the new parameter
|
||||
* value. For program parameters, a callback shall be installed which calls update
|
||||
* directly after setting the parameter. Thus notification callbacks shall always be
|
||||
* connected to the update chain.
|
||||
*
|
||||
* copyright: GPL
|
||||
*
|
||||
@ -23,12 +25,14 @@
|
||||
#define HIPADABA
|
||||
|
||||
/*------- datatypes */
|
||||
#define HIPNONE -1
|
||||
#define HIPINT 0
|
||||
#define HIPFLOAT 1
|
||||
#define HIPTEXT 2
|
||||
#define HIPINTAR 3
|
||||
#define HIPFLOATAR 4
|
||||
#define HIPNONE -1
|
||||
#define HIPINT 0
|
||||
#define HIPFLOAT 1
|
||||
#define HIPTEXT 2
|
||||
#define HIPINTAR 3
|
||||
#define HIPFLOATAR 4
|
||||
#define HIPINTVARAR 5
|
||||
#define HIPFLOATVARAR 6
|
||||
/* -------- callback types */
|
||||
#define HCBSET 0
|
||||
#define HCBUPDATE 1
|
||||
|
4
lld.c
4
lld.c
@ -208,6 +208,10 @@ void LLDdelete( int List )
|
||||
|
||||
assert( (unsigned) List < ListCount );
|
||||
|
||||
if(ListControl == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Tmp = ListControl[ List ].first ; /* dummies are also deleted !!! */
|
||||
while( NULL != Tmp ) /* still assuming last node has */
|
||||
{ /* a NULL next pointer ... */
|
||||
|
2
motor.c
2
motor.c
@ -492,7 +492,7 @@ extern void KillPiPiezo(void *pData);
|
||||
|
||||
pM = (pMotor)self;
|
||||
|
||||
MotorHalt(pM);
|
||||
/* MotorHalt(pM); */
|
||||
|
||||
if(pM->name)
|
||||
free(pM->name);
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "site.h"
|
||||
#include "tcldrivable.h"
|
||||
#include "nserver.h"
|
||||
#include "sicshipadaba.h"
|
||||
|
||||
int ServerSetupInterrupt(int iPort, pNetRead pNet, pTaskMan pTasker);
|
||||
/*
|
||||
@ -396,6 +397,7 @@
|
||||
|
||||
KillFreeConnections();
|
||||
|
||||
killSICSHipadaba();
|
||||
|
||||
/* make fortify print his findings */
|
||||
Fortify_DumpAllMemory(iFortifyScope);
|
||||
|
10
obdes.c
10
obdes.c
@ -44,6 +44,7 @@
|
||||
#include "obdes.h"
|
||||
#include "conman.h"
|
||||
#include "servlog.h"
|
||||
#include "hipadaba.h"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void *DefaultGetInterface(void *pData,int iID)
|
||||
@ -67,6 +68,7 @@
|
||||
}
|
||||
pRes->name = strdup(name);
|
||||
pRes->pKeys = NULL;
|
||||
pRes->parNode = NULL;
|
||||
pRes->SaveStatus = DefaultSave;
|
||||
pRes->GetInterface = DefaultGetInterface;
|
||||
return pRes;
|
||||
@ -77,6 +79,14 @@
|
||||
assert(self);
|
||||
if(self->name) free(self->name);
|
||||
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);
|
||||
|
||||
}
|
||||
|
2
obdes.h
2
obdes.h
@ -23,12 +23,14 @@
|
||||
#define SICSDESCRIPTOR
|
||||
#include <stdio.h>
|
||||
#include <ifile.h>
|
||||
#include <hipadaba.h>
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
int (*SaveStatus)(void *self, char *name,FILE *fd);
|
||||
void *(*GetInterface)(void *self, int iInterfaceID);
|
||||
IPair *pKeys;
|
||||
pHdb parNode;
|
||||
} ObjectDescriptor, *pObjectDescriptor;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
2
ofac.c
2
ofac.c
@ -376,7 +376,7 @@
|
||||
RemoveCommand(pSics,"MakeLin2Ang");
|
||||
RemoveCommand(pSics,"MakeSync");
|
||||
RemoveCommand(pSics,"MakeHMControl");
|
||||
/* RemoveCommand(pSics,"MakeRS232Controller"); */
|
||||
RemoveCommand(pSics,"MakeRS232Controller");
|
||||
RemoveCommand(pSics,"MakeMaxDetector");
|
||||
RemoveCommand(pSics,"AntiColliderInstall");
|
||||
RemoveCommand(pSics,"MakeGPIB");
|
||||
|
336
sicshipadaba.c
336
sicshipadaba.c
@ -13,6 +13,7 @@
|
||||
#include <ctype.h>
|
||||
#include <sicshipadaba.h>
|
||||
#include <lld.h>
|
||||
#include <stptok.h>
|
||||
|
||||
/*== there can be only hipadaba in SICS, some globals to care for that == */
|
||||
static pHdb root = NULL;
|
||||
@ -27,12 +28,22 @@ static int SICSCheckPermissionCallback(void *userData, void *callData, pHdb node
|
||||
pCon = (SConnection *)callData;
|
||||
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){
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
return SICSCBPERM;
|
||||
}
|
||||
}
|
||||
/*--------------------------------------------------------------------------------------*/
|
||||
@ -60,10 +71,11 @@ static int SICSReadOnlyCallback(void *userData, void *callData, pHdb node,
|
||||
SConnection *pCon = NULL;
|
||||
|
||||
pCon = (SConnection *)callData;
|
||||
assert(pCon != NULL);
|
||||
|
||||
SCWrite(pCon,"ERROR: parameter is READ-ONLY", eError);
|
||||
return 0;
|
||||
if(pCon != NULL){
|
||||
SCWrite(pCon,"ERROR: parameter is READ-ONLY", eError);
|
||||
}
|
||||
return SICSCBRO;
|
||||
}
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
static pHdbCallback MakeReadOnlyCallback(){
|
||||
@ -86,6 +98,31 @@ pHdbCallback MakeSICSDriveCallback(void *sicsObject){
|
||||
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 {
|
||||
SConnection *pCon;
|
||||
commandContext context;
|
||||
@ -228,11 +265,144 @@ static int SICSScriptReadCallback(void *userData, void *callData, pHdb node,
|
||||
}
|
||||
return status;
|
||||
}
|
||||
/*----------------------------------------------------------------------------------------*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
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 result = NULL;
|
||||
pHdbCallback pHcb = NULL;
|
||||
@ -283,10 +453,17 @@ pHdb MakeSICSHdbDriv(char *name, int priv, void *sicsObject, int dataType){
|
||||
}
|
||||
AppendHipadabaCallback(result,HCBSET,pHcb);
|
||||
|
||||
pHcb = MakeSICSReadDriveCallback(sicsObject);
|
||||
if(pHcb == NULL){
|
||||
DeleteHipadabaNode(result);
|
||||
return NULL;
|
||||
}
|
||||
AppendHipadabaCallback(result,HCBREAD,pHcb);
|
||||
|
||||
return result;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
pHdb MakeSICSHdbROPar(char *name, int priv, hdbValue v){
|
||||
pHdb MakeSICSROPar(char *name, hdbValue v){
|
||||
pHdb result = NULL;
|
||||
pHdbCallback pHcb = NULL;
|
||||
|
||||
@ -296,7 +473,7 @@ pHdb MakeSICSHdbROPar(char *name, int priv, hdbValue v){
|
||||
}
|
||||
copyHdbValue(&v,&result->value);
|
||||
|
||||
pHcb = MakeReadOnlyCallback(priv);
|
||||
pHcb = MakeReadOnlyCallback();
|
||||
if(pHcb == NULL){
|
||||
DeleteHipadabaNode(result);
|
||||
return NULL;
|
||||
@ -498,6 +675,9 @@ int SICSHipadabaTask(void *pData){
|
||||
if(self->iEnd == 1){
|
||||
return 0;
|
||||
}
|
||||
if(LLDcheck(self->updateList) == LIST_EMPTY){
|
||||
return 1;
|
||||
}
|
||||
memset(&old,0,sizeof(hdbValue));
|
||||
memset(&newValue,0,sizeof(hdbValue));
|
||||
|
||||
@ -561,12 +741,14 @@ pDynString formatValue(hdbValue v){
|
||||
DynStringCopy(result,v.v.text);
|
||||
break;
|
||||
case HIPINTAR:
|
||||
case HIPINTVARAR:
|
||||
for(i = 0; i < v.arrayLength; i++){
|
||||
snprintf(number,30," %ld", v.v.intArray[i]);
|
||||
DynStringConcat(result,number);
|
||||
}
|
||||
break;
|
||||
case HIPFLOATAR:
|
||||
case HIPFLOATVARAR:
|
||||
for(i = 0; i < v.arrayLength; i++){
|
||||
snprintf(number,30," %12.4f", v.v.floatArray[i]);
|
||||
DynStringConcat(result,number);
|
||||
@ -597,7 +779,39 @@ static char *getNextHdbNumber(char *pStart, char pNumber[80]){
|
||||
pNumber[charCount] = '\0';
|
||||
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 i, status;
|
||||
@ -633,6 +847,11 @@ int readHdbValue(hdbValue *v, char *data, char *error, int errlen){
|
||||
}
|
||||
v->v.text = strdup(data);
|
||||
break;
|
||||
case HIPINTVARAR:
|
||||
if(!adjustDataLength(v,data)){
|
||||
snprintf(error,errlen,"Out of memory allocating variable length data");
|
||||
return 0;
|
||||
}
|
||||
case HIPINTAR:
|
||||
for(i = 0; i < v->arrayLength; i++){
|
||||
data = getNextHdbNumber(data,number);
|
||||
@ -650,6 +869,11 @@ int readHdbValue(hdbValue *v, char *data, char *error, int errlen){
|
||||
v->v.intArray[i] = lValue;
|
||||
}
|
||||
break;
|
||||
case HIPFLOATVARAR:
|
||||
if(!adjustDataLength(v,data)){
|
||||
snprintf(error,errlen,"Out of memory allocating variable length data");
|
||||
return 0;
|
||||
}
|
||||
case HIPFLOATAR:
|
||||
for(i = 0; i < v->arrayLength; i++){
|
||||
data = getNextHdbNumber(data,number);
|
||||
@ -684,6 +908,8 @@ static char *hdbTypes[] = {"none",
|
||||
"text",
|
||||
"intar",
|
||||
"floatar",
|
||||
"intvarar",
|
||||
"floatvarar",
|
||||
NULL};
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int convertHdbType(char *text){
|
||||
@ -729,9 +955,9 @@ static int MakeHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
*/
|
||||
strtolower(argv[3]);
|
||||
type = convertHdbType(argv[3]);
|
||||
if(type >= 5){
|
||||
if(type >= 7){
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
@ -800,9 +1026,9 @@ static int MakeHdbScriptNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
*/
|
||||
strtolower(argv[4]);
|
||||
type = convertHdbType(argv[4]);
|
||||
if(type >= 5){
|
||||
if(type >= 7){
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
@ -868,7 +1094,46 @@ static int DeleteHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
SCSendOK(pCon);
|
||||
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,
|
||||
int argc, char *argv[]){
|
||||
pHdb targetNode = NULL;
|
||||
@ -887,10 +1152,8 @@ static int SetHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
return 0;
|
||||
}
|
||||
|
||||
targetNode = GetHipadabaNode(root,argv[1]);
|
||||
targetNode = locateSICSNode(pSics,pCon,argv[1]);
|
||||
if(targetNode == NULL){
|
||||
SCWrite(pCon,"ERROR: node to set not found!",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
if(!cloneHdbValue(&targetNode->value,&newValue)){
|
||||
@ -936,10 +1199,8 @@ static int GetHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
}
|
||||
|
||||
strncpy(oriPath,argv[1], 511);
|
||||
targetNode = GetHipadabaNode(root,argv[1]);
|
||||
targetNode = locateSICSNode(pSics,pCon,argv[1]);
|
||||
if(targetNode == NULL){
|
||||
SCWrite(pCon,"ERROR: node to read not found!",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
memset(&newValue,0,sizeof(hdbValue));
|
||||
@ -1057,6 +1318,7 @@ static pDynString formatClientList(pHdb node){
|
||||
DynStringConcat(result,current->value.v.text);
|
||||
break;
|
||||
case HIPINTAR:
|
||||
case HIPINTVARAR:
|
||||
for(i = 0; i < length; i++){
|
||||
snprintf(number,50,"%ld",current->value.v.intArray[i]);
|
||||
DynStringConcat(result,number);
|
||||
@ -1066,6 +1328,7 @@ static pDynString formatClientList(pHdb node){
|
||||
}
|
||||
break;
|
||||
case HIPFLOATAR:
|
||||
case HIPFLOATVARAR:
|
||||
for(i = 0; i < length; i++){
|
||||
snprintf(number,50,"%lf",current->value.v.floatArray[i]);
|
||||
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){
|
||||
SCWrite(pCon,"ERROR: node to list not found!",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1136,10 +1397,8 @@ static int AutoNotifyHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
return 0;
|
||||
}
|
||||
|
||||
node = GetHipadabaNode(root,argv[1]);
|
||||
node = locateSICSNode(pSics,pCon,argv[1]);
|
||||
if(node == NULL){
|
||||
SCWrite(pCon,"ERROR: node to add notify found!",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1168,15 +1427,18 @@ static int RemoveHdbCallback(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void killSICSHipadaba(void *pData){
|
||||
DeleteHipadabaNode(root);
|
||||
void killSICSHipadaba(){
|
||||
if(root != NULL){
|
||||
DeleteHipadabaNode(root);
|
||||
}
|
||||
root = NULL;
|
||||
/**
|
||||
* children have already been removed when killing the
|
||||
* main tree
|
||||
*/
|
||||
/**
|
||||
* children have already been removed when killing the
|
||||
* main tree
|
||||
*/
|
||||
if(scriptUpdate > 0 && LLDcheck(scriptUpdate) != LIST_EMPTY){
|
||||
LLDdelete(scriptUpdate);
|
||||
SCDeleteConnection(taskData.pCon);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int InstallSICSHipadaba(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
@ -1194,10 +1456,10 @@ int InstallSICSHipadaba(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
TaskRegister(pServ->pTasker,
|
||||
SICSHipadabaTask,
|
||||
SICSHipadabaSignal,
|
||||
killSICSHipadaba,
|
||||
NULL,
|
||||
&taskData,1);
|
||||
|
||||
AddCommand(pSics,"hmake", MakeHdbNode, killSICSHipadaba, NULL);
|
||||
AddCommand(pSics,"hmake", MakeHdbNode, NULL, NULL);
|
||||
AddCommand(pSics,"hmakescript", MakeHdbScriptNode, NULL, NULL);
|
||||
AddCommand(pSics,"hdel", DeleteHdbNode, NULL, NULL);
|
||||
AddCommand(pSics,"hset", SetHdbNode, NULL, NULL);
|
||||
|
@ -12,6 +12,11 @@
|
||||
#include <hipadaba.h>
|
||||
#include <sics.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 =======*/
|
||||
typedef struct {
|
||||
SConnection *pCon;
|
||||
@ -40,6 +45,13 @@ pHdbCallback MakeSetUpdateCallback();
|
||||
* starting a parameter driving.
|
||||
*/
|
||||
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
|
||||
* notification of pCon on parameter updates.
|
||||
@ -51,6 +63,33 @@ pHdbCallback MakeSICSDriveCallback(void *sicsObject);
|
||||
* automatic notification.
|
||||
*/
|
||||
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 ===================================*/
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
pHdb GetHipadabaRoot();
|
||||
|
||||
/**
|
||||
* kill the SICS hierarchical database
|
||||
* Only to be called when shutting down the SICServer
|
||||
*/
|
||||
void killSICSHipadaba(void);
|
||||
#endif /*SICSHIPADABA_H_*/
|
||||
|
Reference in New Issue
Block a user