- 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)
{
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;

View File

@ -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,

View File

@ -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.

View File

@ -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.

View File

@ -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,9 +432,6 @@
LLDnodeDataTo(self->iList,&pDev);
if(pDev)
{
/*
SCSetContext(self->pOwner,pDev->cmdID,pDev->name);
*/
SCPushContext(self->pOwner, pDev->comCon.transID, pDev->comCon.deviceID);
pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData,DRIVEID);

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){
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);

View File

@ -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
*
@ -29,6 +31,8 @@
#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
View File

@ -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 ... */

View File

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

View File

@ -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
View File

@ -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);
}

View File

@ -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
View File

@ -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");

View File

@ -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);
if(pCon != NULL){
SCWrite(pCon,"ERROR: parameter is READ-ONLY", eError);
return 0;
}
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){
void killSICSHipadaba(){
if(root != NULL){
DeleteHipadabaNode(root);
}
root = NULL;
/**
* 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);

View File

@ -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_*/