- Added a SICS to Hipadaba adapter
- Added a separate polling module to SICS
This commit is contained in:
3
event.c
3
event.c
@ -64,6 +64,9 @@
|
||||
"BATCHAREA",
|
||||
"BATCHEND",
|
||||
"DRIVSTAT",
|
||||
"STATUS",
|
||||
"POSITION",
|
||||
"HDBVAL",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
16
event.h
16
event.h
@ -1,5 +1,5 @@
|
||||
|
||||
#line 89 "event.w"
|
||||
#line 96 "event.w"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
E V E N T
|
||||
@ -18,7 +18,7 @@
|
||||
|
||||
int Text2Event(char *pText);
|
||||
|
||||
#line 102 "event.w"
|
||||
#line 109 "event.w"
|
||||
|
||||
|
||||
|
||||
@ -42,14 +42,16 @@
|
||||
#define BATCHAREA 15
|
||||
#define BATCHEND 16
|
||||
#define DRIVSTAT 17
|
||||
#define STATUS 18
|
||||
#define POSITION 19 /* Position event for motors - ffr */
|
||||
#line 104 "event.w"
|
||||
#define STATUS 18
|
||||
#define POSITION 19
|
||||
#define HDBVAL 20
|
||||
|
||||
#line 111 "event.w"
|
||||
|
||||
|
||||
/*--------------- Signals for the Signalfunction of each task ------------*/
|
||||
|
||||
#line 73 "event.w"
|
||||
#line 80 "event.w"
|
||||
|
||||
#define SICSINT 300
|
||||
#define SICSBROADCAST 301
|
||||
@ -57,6 +59,6 @@
|
||||
#define TOKENRELEASE 303
|
||||
#define COMLOG 304
|
||||
|
||||
#line 107 "event.w"
|
||||
#line 114 "event.w"
|
||||
|
||||
#endif
|
||||
|
@ -53,6 +53,9 @@ $\langle$VE {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@#define BATCHAREA 15@\\
|
||||
\mbox{}\verb@#define BATCHEND 16@\\
|
||||
\mbox{}\verb@#define DRIVSTAT 17@\\
|
||||
\mbox{}\verb@#define STATUS 18@\\
|
||||
\mbox{}\verb@#define POSITION 19@\\
|
||||
\mbox{}\verb@#define HDBVAL 20@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
@ -87,6 +90,10 @@ operation.
|
||||
\item[BATCHEND] signals the end of the batch buffers processing.
|
||||
\item[DRIVSTAT] signals a change in the status of a driving operation
|
||||
(start, finished, fault)
|
||||
\item[STATUS] ANSTO defined code.
|
||||
\item[POSITION] ANSTO defined code
|
||||
\item[HDBVAL] The Hdb is notified of a value change. The eventData will be
|
||||
the object on which the data changed.
|
||||
\end{description}
|
||||
|
||||
Furthermore event contains system wide signal codes which are interpreted in
|
||||
|
7
event.w
7
event.w
@ -36,6 +36,9 @@ if the event code is not known, else the apropriate event code.
|
||||
#define BATCHAREA 15
|
||||
#define BATCHEND 16
|
||||
#define DRIVSTAT 17
|
||||
#define STATUS 18
|
||||
#define POSITION 19
|
||||
#define HDBVAL 20
|
||||
@}
|
||||
\begin{description}
|
||||
\item[VALUECHANGE] This is a variable changing its value. As event data a pointer to the
|
||||
@ -62,6 +65,10 @@ operation.
|
||||
\item[BATCHEND] signals the end of the batch buffers processing.
|
||||
\item[DRIVSTAT] signals a change in the status of a driving operation
|
||||
(start, finished, fault)
|
||||
\item[STATUS] ANSTO defined code.
|
||||
\item[POSITION] ANSTO defined code
|
||||
\item[HDBVAL] The Hdb is notified of a value change. The eventData will be
|
||||
the object on which the data changed.
|
||||
\end{description}
|
||||
|
||||
Furthermore event contains system wide signal codes which are interpreted in
|
||||
|
@ -64,7 +64,7 @@ void AppendCommandParameter(pHdbCommand command, pHdb par){
|
||||
assert(command != NULL);
|
||||
assert(par != NULL);
|
||||
|
||||
AddHipadabaChild(command->parameters,par);
|
||||
AddHipadabaChild(command->parameters,par,NULL);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void KillHdbCommandList(pHdbCommand commandList){
|
||||
@ -79,7 +79,7 @@ void KillHdbCommandList(pHdbCommand commandList){
|
||||
free(current->name);
|
||||
}
|
||||
if(current->parameters != NULL){
|
||||
DeleteHipadabaNode(current->parameters);
|
||||
DeleteHipadabaNode(current->parameters,NULL);
|
||||
}
|
||||
free(current);
|
||||
current = next;
|
||||
|
65
hipadaba.c
65
hipadaba.c
@ -38,6 +38,7 @@ static void DeleteNodeData(pHdb node){
|
||||
DeleteCallbackChain(node->writeCallbacks);
|
||||
DeleteCallbackChain(node->updateCallbacks);
|
||||
DeleteCallbackChain(node->readCallbacks);
|
||||
DeleteCallbackChain(node->treeChangeCallbacks);
|
||||
|
||||
if(node->name != NULL){
|
||||
free(node->name);
|
||||
@ -52,8 +53,24 @@ static void DeleteNodeData(pHdb node){
|
||||
}
|
||||
free(node);
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int InvokeCallbackChain(pHdbCallback root, pHdb node,
|
||||
void *callData, hdbValue v){
|
||||
pHdbCallback current = root;
|
||||
int status;
|
||||
|
||||
while(current != NULL){
|
||||
status = current->userCallback(current->userData,callData,
|
||||
node,v);
|
||||
if(status != 1){
|
||||
return status;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void RemoveHdbNodeFromParent(pHdb node){
|
||||
void RemoveHdbNodeFromParent(pHdb node, void *callData){
|
||||
pHdb parent = NULL;
|
||||
pHdb current = NULL;
|
||||
|
||||
@ -68,6 +85,8 @@ void RemoveHdbNodeFromParent(pHdb node){
|
||||
current = current->next;
|
||||
}
|
||||
current->next = current->next->next;
|
||||
InvokeCallbackChain(parent->treeChangeCallbacks,
|
||||
parent,callData,parent->value);
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
@ -174,22 +193,6 @@ static pHdbCallback DeleteForInternalID(pHdbCallback root, int id){
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int InvokeCallbackChain(pHdbCallback root, pHdb node,
|
||||
void *callData, hdbValue v){
|
||||
pHdbCallback current = root;
|
||||
int status;
|
||||
|
||||
while(current != NULL){
|
||||
status = current->userCallback(current->userData,callData,
|
||||
node,v);
|
||||
if(status != 1){
|
||||
return status;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
char *hdbTrim(char *str)
|
||||
{
|
||||
@ -553,7 +556,7 @@ pHdb MakeHipadabaNode(char *name, int datatype, int length){
|
||||
return pNew;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void AddHipadabaChild(pHdb parent, pHdb child){
|
||||
void AddHipadabaChild(pHdb parent, pHdb child, void *callData){
|
||||
pHdb current = NULL, prev = NULL;
|
||||
|
||||
assert(parent != NULL);
|
||||
@ -577,16 +580,18 @@ void AddHipadabaChild(pHdb parent, pHdb child){
|
||||
child->next = NULL;
|
||||
prev->next = child;
|
||||
}
|
||||
InvokeCallbackChain(parent->treeChangeCallbacks,
|
||||
parent,callData,parent->value);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void DeleteHipadabaNode(pHdb node){
|
||||
void DeleteHipadabaNode(pHdb node, void *callData){
|
||||
pHdb current = NULL, tmp = NULL;
|
||||
|
||||
if(node == NULL){
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveHdbNodeFromParent(node);
|
||||
RemoveHdbNodeFromParent(node, callData);
|
||||
|
||||
DeleteNodeData(node);
|
||||
}
|
||||
@ -733,6 +738,14 @@ void AppendHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
|
||||
current = node->readCallbacks;
|
||||
}
|
||||
break;
|
||||
case HCBTREE:
|
||||
if(node->treeChangeCallbacks == NULL){
|
||||
node->treeChangeCallbacks = newCB;
|
||||
return;
|
||||
} else {
|
||||
current = node->treeChangeCallbacks;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
@ -778,6 +791,16 @@ void PrependHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
|
||||
node->readCallbacks = newCB;
|
||||
}
|
||||
break;
|
||||
case HCBTREE:
|
||||
if(node->treeChangeCallbacks == NULL){
|
||||
node->treeChangeCallbacks = newCB;
|
||||
return;
|
||||
} else {
|
||||
newCB->next = node->treeChangeCallbacks;
|
||||
node->treeChangeCallbacks->previous = newCB;
|
||||
node->treeChangeCallbacks = newCB;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
@ -790,6 +813,7 @@ void RemoveHipadabaCallback(pHdb root, int id){
|
||||
root->writeCallbacks = DeleteForID(root->writeCallbacks,id);
|
||||
root->updateCallbacks = DeleteForID(root->updateCallbacks,id);
|
||||
root->readCallbacks = DeleteForID(root->readCallbacks,id);
|
||||
root->treeChangeCallbacks = DeleteForID(root->treeChangeCallbacks,id);
|
||||
|
||||
current = root->child;
|
||||
while(current != NULL){
|
||||
@ -804,6 +828,7 @@ void InternalRemoveHipadabaCallback(pHdb root, int internalID){
|
||||
root->writeCallbacks = DeleteForInternalID(root->writeCallbacks,internalID);
|
||||
root->updateCallbacks = DeleteForInternalID(root->updateCallbacks,internalID);
|
||||
root->readCallbacks = DeleteForInternalID(root->readCallbacks,internalID);
|
||||
root->treeChangeCallbacks = DeleteForInternalID(root->treeChangeCallbacks,internalID);
|
||||
|
||||
current = root->child;
|
||||
while(current != NULL){
|
||||
|
18
hipadaba.h
18
hipadaba.h
@ -20,6 +20,8 @@
|
||||
* copyright: GPL
|
||||
*
|
||||
* Mark Koennecke, June 2006
|
||||
*
|
||||
* Added treeChange callback, Mark Koennecke, November 2006
|
||||
*/
|
||||
#ifndef HIPADABA
|
||||
#define HIPADABA
|
||||
@ -38,6 +40,7 @@
|
||||
#define HCBSET 0
|
||||
#define HCBUPDATE 1
|
||||
#define HCBREAD 2
|
||||
#define HCBTREE 3
|
||||
/*--------- error codes */
|
||||
#define HDBTYPEMISMATCH -7701
|
||||
#define HDBLENGTHMISMATCH -7702
|
||||
@ -63,12 +66,14 @@ typedef struct __hipadaba {
|
||||
struct __hdbcallback *writeCallbacks;
|
||||
struct __hdbcallback *updateCallbacks;
|
||||
struct __hdbcallback *readCallbacks;
|
||||
struct __hdbcallback *treeChangeCallbacks;
|
||||
char *name;
|
||||
hdbValue value;
|
||||
int protected;
|
||||
}Hdb, *pHdb;
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
typedef int (*hdbCallbackFunction)(void *userData, void *callData,
|
||||
pHdb currentNode, hdbValue v );
|
||||
pHdb currentNode, hdbValue v);
|
||||
typedef void (*killUserData)(void *data);
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
typedef struct __hdbcallback {
|
||||
@ -179,13 +184,15 @@ pHdb MakeHipadabaNode(char *name, int datatype, int length);
|
||||
* add a child to a node at the end of the child list.
|
||||
* @param parent The node to which to add the child
|
||||
* @param child The node to add
|
||||
* @param callData User data for the tree chnage callback. Can be NULL.
|
||||
*/
|
||||
void AddHipadabaChild(pHdb parent, pHdb child);
|
||||
void AddHipadabaChild(pHdb parent, pHdb child, void *callData);
|
||||
/**
|
||||
* delete a hipadaba node and all its children
|
||||
* @parma node The node to delete
|
||||
* @param callData User data for the tree change callback
|
||||
*/
|
||||
void DeleteHipadabaNode(pHdb node);
|
||||
void DeleteHipadabaNode(pHdb node, void *callData);
|
||||
/*
|
||||
* checks if a Hdb node is valid
|
||||
* @param node The node to check
|
||||
@ -209,8 +216,9 @@ char *GetHipadabaPath(pHdb node);
|
||||
/**
|
||||
* removes a node from the parents child list.
|
||||
* @node the node to remove
|
||||
* @param callData User data for the tree change callback
|
||||
*/
|
||||
void RemoveHdbNodeFromParent(pHdb node);
|
||||
void RemoveHdbNodeFromParent(pHdb node, void *callData);
|
||||
/**
|
||||
* delete a callback chain
|
||||
* @param root The callback chain to delete
|
||||
@ -300,7 +308,7 @@ int SetHdbPar(pHdb node, int dataType, void *data, int length,
|
||||
void *callData);
|
||||
/**
|
||||
* Updates a hipadaba parameter. This does not cause an active parameter to
|
||||
* start driving but invokes all nitifications which may be regsitered on
|
||||
* start driving but invokes all notifications which may be registered on
|
||||
* this parameter.
|
||||
* @param node The node for which to set the parameter
|
||||
* param dataType The datatype the value ought to have
|
||||
|
37
histmem.c
37
histmem.c
@ -1238,13 +1238,19 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
}
|
||||
else if(strcmp(argv[1],"init") == 0)
|
||||
{
|
||||
if(GetStatus() != eEager)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: cannot initialize HM while running",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
if(SCMatchRights(pCon,usMugger))
|
||||
{
|
||||
iRet = HistConfigure(self,pCon,pSics);
|
||||
if(iRet)
|
||||
{
|
||||
self->iInit = 1;
|
||||
SCSendOK(pCon);
|
||||
SCSendOK(pCon);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1362,6 +1368,31 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
}
|
||||
return iRet;
|
||||
}
|
||||
else if(strcmp(argv[1],"initfile") == 0) /* initialize from a file */
|
||||
{
|
||||
/* check user rights */
|
||||
if(!SCMatchRights(pCon,self->iAccess))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* enough arguments */
|
||||
if(argc < 3)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: insufficient number of arguments to %s %s",
|
||||
argv[0], argv[1]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
iRet = loadHMData(self->pDriv->data,pCon,argv[2]);
|
||||
self->pDriv->SetHistogram(self->pDriv,pCon,0,0,GetHistLength(self),
|
||||
self->pDriv->data->localBuffer);
|
||||
if(iRet)
|
||||
{
|
||||
SCSendOK(pCon);
|
||||
}
|
||||
return iRet;
|
||||
}
|
||||
else if(strcmp(argv[1],"get") == 0) /* get a histogram */
|
||||
{
|
||||
/* check parameters, first required: no of Hist */
|
||||
@ -1602,8 +1633,8 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
return 0;
|
||||
}
|
||||
if(GetStatus() == eCounting)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: cannot modify timebinning while counting",
|
||||
{
|
||||
SCWrite(pCon,"ERROR: cannot modify timebinning while counting",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
|
@ -183,6 +183,13 @@
|
||||
lData[ii-iStart] = iSetVal;
|
||||
}
|
||||
}
|
||||
else if(iSet == 2)
|
||||
{
|
||||
for(ii = iStart; ii < iEnd; ii++)
|
||||
{
|
||||
lData[ii-iStart] = self->data->localBuffer[ii];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(ii = iStart; ii < iEnd; ii++)
|
||||
@ -196,7 +203,7 @@
|
||||
static int SimSetHistogram(pHistDriver self, SConnection *pCon,
|
||||
int i, int iStart, int iEnd, HistInt *lData)
|
||||
{
|
||||
iSet = 1;
|
||||
iSet = 2;
|
||||
iSetVal = lData[0];
|
||||
return 1;
|
||||
}
|
||||
|
50
hmdata.c
50
hmdata.c
@ -5,11 +5,15 @@
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, January 2003
|
||||
|
||||
Added loading HM data from file, Mark Koennecke, November 2006
|
||||
-------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include "splitter.h"
|
||||
#include "fortify.h"
|
||||
#include "hmdata.h"
|
||||
#include "HistMem.h"
|
||||
@ -410,7 +414,7 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
|
||||
iStart[0], iEnd[0]);
|
||||
break;
|
||||
case 2:
|
||||
/*
|
||||
|
||||
lSum = 0;
|
||||
for(i = iStart[1]; i < iEnd[1]; i++){
|
||||
iIndex = i*self->iDim[0];
|
||||
@ -418,7 +422,8 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
|
||||
iIndex+iStart[0], iIndex+iEnd[0]);
|
||||
lSum += lRowSum;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
* This is wrong, see the bit about x and y somewhere
|
||||
lSum = 0;
|
||||
for(i = iStart[0]; i < iEnd[0]; i++){
|
||||
iIndex = i*self->iDim[1];
|
||||
@ -426,6 +431,7 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
|
||||
iIndex+iStart[1], iIndex+iEnd[1]);
|
||||
lSum += lRowSum;
|
||||
}
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
sprintf(pBueffel,
|
||||
@ -440,3 +446,43 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
|
||||
}
|
||||
return lSum;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int loadHMData(pHMdata self, SConnection *pCon, char *filename){
|
||||
FILE *fd = NULL;
|
||||
char buffer[1024], pNumber[80], *pPtr;
|
||||
long i = 0, length;
|
||||
HistInt *data = NULL;
|
||||
|
||||
fd = fopen(filename,"r");
|
||||
if(fd == NULL){
|
||||
snprintf(buffer,1023,"ERROR: failed to open file %s", filename);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
return 0;
|
||||
}
|
||||
length = getHMDataLength(self);
|
||||
if(self->localBuffer == NULL || self->timeslave != NULL){
|
||||
resizeBuffer(self);
|
||||
}
|
||||
data = self->localBuffer;
|
||||
if(data == NULL){
|
||||
SCWrite(pCon,"ERROR: failed to allocate HM", eError);
|
||||
fclose(fd);
|
||||
return 0;
|
||||
}
|
||||
while(i < length && fgets(buffer,1024,fd) != NULL){
|
||||
pPtr = buffer;
|
||||
while(pPtr != NULL){
|
||||
pPtr = sicsNextNumber(pPtr,pNumber);
|
||||
if(pPtr != NULL){
|
||||
data[i] = atoi(pNumber);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(i < length-1){
|
||||
SCWrite(pCon,"WARNING: not enough data in file to fill HM",eWarning);
|
||||
}
|
||||
fclose(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
1
hmdata.h
1
hmdata.h
@ -57,6 +57,7 @@
|
||||
|
||||
long sumHMDataRectangle(pHistMem self, SConnection *pCon,
|
||||
int start[MAXDIM], int end[MAXDIM]);
|
||||
int loadHMData(pHMdata self, SConnection *pCon, char *filename);
|
||||
|
||||
|
||||
#endif
|
||||
|
3
hmdata.w
3
hmdata.w
@ -53,6 +53,7 @@ The following functions work on this data structure:
|
||||
|
||||
long sumHMDataRectangle(pHistMem self, SConnection *pCon,
|
||||
int start[MAXDIM], int end[MAXDIM]);
|
||||
int loadHMData(pHMdata self, SConnection *pCon, char *filename);
|
||||
@}
|
||||
|
||||
\begin{description}
|
||||
@ -84,6 +85,8 @@ the histogram memory and not from the buffer the next time round.
|
||||
pointer of HMdata. Use with extra care!
|
||||
\item[sumHMDataRectangle] sums a rectangular box delimted by start and end
|
||||
from the histogram memory.
|
||||
\item[loadHMData] loads histogram memory data from a file. This is for
|
||||
debugging purposes. The file must contain enough numbers to fill the HM.
|
||||
\end{description}
|
||||
|
||||
|
||||
|
11
make_gen
11
make_gen
@ -31,14 +31,21 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
||||
hmdata.o nxscript.o tclintimpl.o sicsdata.o mcstascounter.o \
|
||||
mcstashm.o initializer.o remob.o tclmotdriv.o protocol.o \
|
||||
sinfox.o sicslist.o cone.o hipadaba.o sicshipadaba.o statistics.o \
|
||||
moregress.o hdbcommand.o multicounter.o regresscter.o histregress.o
|
||||
moregress.o hdbcommand.o multicounter.o regresscter.o histregress.o \
|
||||
sicshdbadapter.o polldriv.o sicspoll.o
|
||||
|
||||
MOTOROBJ = motor.o simdriv.o
|
||||
COUNTEROBJ = countdriv.o simcter.o counter.o
|
||||
VELOOBJ = velo.o velosim.o
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .tcl .htm .c .o
|
||||
.SUFFIXES: .tcl .htm .c .o .tc
|
||||
|
||||
.tc.c:
|
||||
tjxp $*.tc $*.c
|
||||
|
||||
#--- This .SECONDARY. target is necessary to preserve generated .c files for debugging
|
||||
.SECONDARY.: sicspoll.c polldriv.c
|
||||
|
||||
all: libmat libhlib libtecsl libpsi SICServer
|
||||
|
||||
|
13
motor.c
13
motor.c
@ -76,13 +76,6 @@
|
||||
#define IGNOREFAULT 10
|
||||
#define MOVECOUNT 11
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
a tiny structure used in CallBack work
|
||||
*/
|
||||
typedef struct {
|
||||
float fVal;
|
||||
char *pName;
|
||||
} MotCallback;
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void *MotorGetInterface(void *pData, int iID)
|
||||
@ -416,7 +409,7 @@ static void handleMoveCallback(pMotor self, SConnection *pCon)
|
||||
|
||||
|
||||
/* create and initialize parameters */
|
||||
pM->ParArray = ObParCreate(12);
|
||||
pM->ParArray = ObParCreate(MOTOBPARLENGTH);
|
||||
if(!pM->ParArray)
|
||||
{
|
||||
free(pM);
|
||||
@ -606,6 +599,7 @@ extern void KillPiPiezo(void *pData);
|
||||
if(iRet == 1)
|
||||
{
|
||||
SCparChange(pCon);
|
||||
InvokeCallBack(self->pCall,HDBVAL,self);
|
||||
return iRet;
|
||||
}
|
||||
}
|
||||
@ -631,6 +625,7 @@ extern void KillPiPiezo(void *pData);
|
||||
fLimit -= fChange;
|
||||
ObParSet(self->ParArray,self->name,"softlowerlim",fLimit,pCon);
|
||||
SCparChange(pCon);
|
||||
InvokeCallBack(self->pCall,HDBVAL,self);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -652,6 +647,7 @@ extern void KillPiPiezo(void *pData);
|
||||
ObParInit(self->ParArray,SZERO,"softzero",ZEROINACTIVE,usUser);
|
||||
}
|
||||
}
|
||||
InvokeCallBack(self->pCall,HDBVAL,self);
|
||||
SCparChange(pCon);
|
||||
|
||||
return iRet;
|
||||
@ -785,6 +781,7 @@ extern void KillPiPiezo(void *pData);
|
||||
self->retryCount = 0;
|
||||
self->stopped = 0;
|
||||
self->fTarget = fHard;
|
||||
InvokeCallBack(self->pCall,HDBVAL,self);
|
||||
self->posCount = 0;
|
||||
iRet = self->pDriver->RunTo(self->pDriver,fHard);
|
||||
if(iRet != OKOK)
|
||||
|
8
motor.h
8
motor.h
@ -14,6 +14,7 @@
|
||||
#include "obdes.h"
|
||||
#include "interface.h"
|
||||
|
||||
#define MOTOBPARLENGTH 12
|
||||
typedef struct __Motor {
|
||||
pObjectDescriptor pDescriptor;
|
||||
ObPar *ParArray;
|
||||
@ -32,6 +33,13 @@
|
||||
int stopped;
|
||||
} Motor;
|
||||
typedef Motor *pMotor;
|
||||
/*------------------------------------------------------------------------
|
||||
a tiny structure used in CallBack work
|
||||
--------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
float fVal;
|
||||
char *pName;
|
||||
} MotCallback;
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* parameter management */
|
||||
|
7
nread.c
7
nread.c
@ -686,6 +686,9 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
|
||||
int iRet, iStatus;
|
||||
int iCount;
|
||||
NetItem NItem;
|
||||
int conCount = 0;
|
||||
char num[50];
|
||||
IPair *options = NULL;
|
||||
|
||||
self = (pNetRead)pData;
|
||||
assert(self);
|
||||
@ -716,9 +719,13 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
|
||||
{
|
||||
iCount = NItem.pSock->sockid;
|
||||
}
|
||||
conCount++;
|
||||
iRet = LLDnodePtr2Next(self->iList);
|
||||
}
|
||||
|
||||
snprintf(num,50,"%d", conCount);
|
||||
IFSetOption(pSICSOptions,"ConnectionCount",num);
|
||||
|
||||
/* the select itself */
|
||||
tmo.tv_usec = self->iReadTimeout;
|
||||
iCount++;
|
||||
|
@ -109,6 +109,8 @@
|
||||
/* initialise tasker */
|
||||
assert(TaskerInit(&self->pTasker));
|
||||
|
||||
pSICSOptions = IFAddOption(pSICSOptions, "ConnectionCount","0");
|
||||
|
||||
/* initialise the server from script */
|
||||
if(file == NULL)
|
||||
{
|
||||
|
2
obdes.c
2
obdes.c
@ -84,7 +84,7 @@
|
||||
*/
|
||||
if(self->parNode != NULL){
|
||||
if(self->parNode->mama == NULL){
|
||||
DeleteHipadabaNode(self->parNode);
|
||||
DeleteHipadabaNode(self->parNode,NULL);
|
||||
}
|
||||
}
|
||||
free(self);
|
||||
|
3
ofac.c
3
ofac.c
@ -120,6 +120,7 @@
|
||||
#include "cone.h"
|
||||
#include "sicshipadaba.h"
|
||||
#include "multicounter.h"
|
||||
#include "sicspoll.h"
|
||||
/*----------------------- Server options creation -------------------------*/
|
||||
static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
@ -331,6 +332,8 @@
|
||||
MakeCone,NULL,NULL);
|
||||
AddCommand(pInter,"MakeMultiCounter",
|
||||
MakeMultiCounter,NULL,NULL);
|
||||
AddCommand(pInter,"MakeSicsPoll",
|
||||
InstallSICSPoll,NULL,NULL);
|
||||
|
||||
/*
|
||||
install site specific commands
|
||||
|
97
polldriv.c
Normal file
97
polldriv.c
Normal file
@ -0,0 +1,97 @@
|
||||
/**
|
||||
* This is the sister module to sicspoll which defines the drivers for the
|
||||
* various modes of polling SICS objects.
|
||||
*
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, November-December 2006
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <sics.h>
|
||||
#include <splitter.h>
|
||||
|
||||
#include "polldriv.h"
|
||||
#include "splitter.h"
|
||||
#include "sicshipadaba.h"
|
||||
/*================ actual driver implementation =========================*/
|
||||
static int timeDue(struct __POLLDRIV *self, time_t now, SConnection *pCon){
|
||||
if(now > self->nextPoll){
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*------------------ HDB Driver -----------------------------------------*/
|
||||
static int pollHdb(struct __POLLDRIV *self, SConnection *pCon){
|
||||
hdbValue old, newVal;
|
||||
pHdb node = NULL;
|
||||
|
||||
memset(&old,0,sizeof(hdbValue));
|
||||
memset(&newVal,0,sizeof(hdbValue));
|
||||
node = (pHdb)self->objPointer;
|
||||
assert(node != NULL);
|
||||
old = node->value;
|
||||
self->nextPoll = time(NULL) + self->pollIntervall;
|
||||
if(GetHipadabaPar(node, &newVal, pCon) == 1){
|
||||
if(!compareHdbValue(old,newVal)){
|
||||
UpdateHipadabaPar(node,newVal,pCon);
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static pPollDriv makeHdbDriver(SConnection *pCon, char *objectIdentifier,
|
||||
int argc, char *argv[]){
|
||||
pHdb root = NULL, node = NULL;
|
||||
pPollDriv pNew = NULL;
|
||||
|
||||
root = GetHipadabaRoot();
|
||||
assert(root != NULL);
|
||||
node = GetHipadabaNode(root,objectIdentifier);
|
||||
if(node == NULL){
|
||||
SCWrite(pCon,"ERROR: object to poll not found",eError);
|
||||
return 0;
|
||||
}
|
||||
pNew = malloc(sizeof(PollDriv));
|
||||
if(pNew == NULL){
|
||||
return NULL;
|
||||
}
|
||||
memset(pNew,0,sizeof(PollDriv));
|
||||
|
||||
|
||||
pNew->objectIdentifier = strdup(objectIdentifier);
|
||||
pNew->objPointer = node;
|
||||
pNew->isDue = timeDue;
|
||||
pNew->poll = pollHdb;
|
||||
|
||||
if(argc > 0){
|
||||
pNew->pollIntervall = atoi(argv[0]);
|
||||
} else {
|
||||
pNew->pollIntervall = 10;
|
||||
}
|
||||
|
||||
return pNew;
|
||||
}
|
||||
/*================ external interface ====================================*/
|
||||
pPollDriv makePollDriver(SConnection *pCon, char *driver,
|
||||
char *objectIdentifier, int argc, char *argv[]){
|
||||
|
||||
strtolower(driver);
|
||||
if(strcmp(driver,"hdb") == 0) {
|
||||
return makeHdbDriver(pCon,objectIdentifier, argc, argv);
|
||||
} else {
|
||||
SCWrite(pCon,"ERROR: polling driver type unknown",eError);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void deletePollDriv(pPollDriv self){
|
||||
if(self->objectIdentifier != NULL){
|
||||
free(self->objectIdentifier);
|
||||
}
|
||||
free(self);
|
||||
}
|
42
polldriv.h
Normal file
42
polldriv.h
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* This is the sister module to sicspoll which defines the drivers for the
|
||||
* various modes of polling SICS objects.
|
||||
*
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, November-December 2006
|
||||
*/
|
||||
#ifndef POLLDRIV_H_
|
||||
#define POLLDRIV_H_
|
||||
#include <time.h>
|
||||
#include <sics.h>
|
||||
/*==================== a data structure ===================================*/
|
||||
typedef struct __POLLDRIV{
|
||||
char *objectIdentifier; /* the object identifier */
|
||||
void *objPointer; /* a pointer to the object */
|
||||
time_t nextPoll; /* next polling time */
|
||||
int pollIntervall; /* poll intervall */
|
||||
int (*isDue)(struct __POLLDRIV *self, time_t now, SConnection *pCon);
|
||||
/* function called to determine if this object must be polled */
|
||||
int (*poll)(struct __POLLDRIV *self, SConnection *pCon);
|
||||
/* the actual polling function */
|
||||
}PollDriv, *pPollDriv;
|
||||
/*==================== the interface =====================================*/
|
||||
/*
|
||||
* make a poll driver
|
||||
* @param pCon A connection to report errors too
|
||||
* @param driver the driver type to generate
|
||||
* @param objectIdentifier An identifer for the object to poll
|
||||
* @param argc number of additional parameter
|
||||
* @param *argv[] Additional parameters.
|
||||
* @return NULL on failure or a PollDriv strucure else.
|
||||
*/
|
||||
pPollDriv makePollDriver(SConnection *pCon, char *driver,
|
||||
char *objectIdentifier, int argc, char *argv[]);
|
||||
/**
|
||||
* free all memory associated with this poll driver
|
||||
* @param self The structure to delete
|
||||
*/
|
||||
void deletePollDriv(pPollDriv self);
|
||||
|
||||
#endif /*POLLDRIV_H_*/
|
88
polldriv.tc
Normal file
88
polldriv.tc
Normal file
@ -0,0 +1,88 @@
|
||||
/**
|
||||
* This is the sister module to sicspoll which defines the drivers for the
|
||||
* various modes of polling SICS objects.
|
||||
*
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, November-December 2006
|
||||
*/
|
||||
<%! source sicstemplates.tcl %>
|
||||
<% stdIncludes %>
|
||||
#include "polldriv.h"
|
||||
#include "splitter.h"
|
||||
#include "sicshipadaba.h"
|
||||
/*================ actual driver implementation =========================*/
|
||||
static int timeDue(struct __POLLDRIV *self, time_t now, SConnection *pCon){
|
||||
if(now > self->nextPoll){
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*------------------ HDB Driver -----------------------------------------*/
|
||||
static int pollHdb(struct __POLLDRIV *self, SConnection *pCon){
|
||||
hdbValue old, newVal;
|
||||
pHdb node = NULL;
|
||||
|
||||
memset(&old,0,sizeof(hdbValue));
|
||||
memset(&newVal,0,sizeof(hdbValue));
|
||||
node = (pHdb)self->objPointer;
|
||||
assert(node != NULL);
|
||||
old = node->value;
|
||||
self->nextPoll = time(NULL) + self->pollIntervall;
|
||||
if(GetHipadabaPar(node, &newVal, pCon) == 1){
|
||||
if(!compareHdbValue(old,newVal)){
|
||||
UpdateHipadabaPar(node,newVal,pCon);
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static pPollDriv makeHdbDriver(SConnection *pCon, char *objectIdentifier,
|
||||
int argc, char *argv[]){
|
||||
pHdb root = NULL, node = NULL;
|
||||
pPollDriv pNew = NULL;
|
||||
|
||||
root = GetHipadabaRoot();
|
||||
assert(root != NULL);
|
||||
node = GetHipadabaNode(root,objectIdentifier);
|
||||
if(node == NULL){
|
||||
SCWrite(pCon,"ERROR: object to poll not found",eError);
|
||||
return 0;
|
||||
}
|
||||
<%newStruc PollDriv 5 %>
|
||||
|
||||
pNew->objectIdentifier = strdup(objectIdentifier);
|
||||
pNew->objPointer = node;
|
||||
pNew->isDue = timeDue;
|
||||
pNew->poll = pollHdb;
|
||||
|
||||
if(argc > 0){
|
||||
pNew->pollIntervall = atoi(argv[0]);
|
||||
} else {
|
||||
pNew->pollIntervall = 10;
|
||||
}
|
||||
|
||||
return pNew;
|
||||
}
|
||||
/*================ external interface ====================================*/
|
||||
pPollDriv makePollDriver(SConnection *pCon, char *driver,
|
||||
char *objectIdentifier, int argc, char *argv[]){
|
||||
|
||||
strtolower(driver);
|
||||
if(strcmp(driver,"hdb") == 0) {
|
||||
return makeHdbDriver(pCon,objectIdentifier, argc, argv);
|
||||
} else {
|
||||
SCWrite(pCon,"ERROR: polling driver type unknown",eError);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void deletePollDriv(pPollDriv self){
|
||||
if(self->objectIdentifier != NULL){
|
||||
free(self->objectIdentifier);
|
||||
}
|
||||
free(self);
|
||||
}
|
471
sicshdbadapter.c
Normal file
471
sicshdbadapter.c
Normal file
@ -0,0 +1,471 @@
|
||||
/*
|
||||
* Experience has shown that integrating existing SICS objects into the
|
||||
* Hierarchical Parameter Database (Hdb) is a difficult task without reworking
|
||||
* the complete SICS object model. Rather, it seems easier to adapt some
|
||||
* critical objects to the Hdb with some glue code. Following the facade or
|
||||
* adapter design pattern. This is the purpose of this module. For the moment
|
||||
* the external interface is only an interpreter function which will be used to
|
||||
* install suitable SICS objects into the Hdb tree and generates the necessary
|
||||
* adapters internally. This code can be used to adapt to:
|
||||
* - motors
|
||||
* - the data segment of histogram memories
|
||||
*
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, November 2006
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <sics.h>
|
||||
#include "stptok.h"
|
||||
#include "motor.h"
|
||||
#include "HistMem.h"
|
||||
#include "sicsvar.h"
|
||||
#include "sicshipadaba.h"
|
||||
#include "sicshdbadapter.h"
|
||||
/*=================== motor code =======================================*/
|
||||
static int MoveCallback(int iEvent, void *eventData, void *userData,
|
||||
commandContext cc){
|
||||
MotCallback *motData = (MotCallback *)eventData;
|
||||
pHdb motor = (pHdb)userData;
|
||||
pHdb pos = NULL;
|
||||
|
||||
if(iEvent == MOTDRIVE && motData != NULL && motor != NULL){
|
||||
UpdateHipadabaPar(motor,MakeHdbFloat((double)motData->fVal)
|
||||
,NULL);
|
||||
pos = GetHipadabaNode(motor,"position");
|
||||
if(pos != NULL){
|
||||
UpdateHipadabaPar(pos,MakeHdbFloat((double)motData->fVal)
|
||||
,NULL);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static int MotorValueCallback(int iEvent, void *eventData, void *userData,
|
||||
commandContext cc){
|
||||
pHdb motor = (pHdb)userData;
|
||||
pMotor pMot = (pMotor)eventData;
|
||||
pHdb current = NULL;
|
||||
float fVal;
|
||||
|
||||
/*
|
||||
* as setting some motor parameters might cause other motor
|
||||
* parametes to change too, I opt for the cheap solution to check
|
||||
* them all.
|
||||
*/
|
||||
if(iEvent == HDBVAL && motor != NULL && pMot != NULL){
|
||||
current = motor->child;
|
||||
while(current != NULL){
|
||||
MotorGetPar(pMot,current->name,&fVal);
|
||||
if(fVal != current->value.v.doubleValue) {
|
||||
UpdateHipadabaPar(current,MakeHdbFloat((double)fVal),NULL);
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static int MotorParSetCallback(void *userData, void *callData,
|
||||
pHdb currentNode, hdbValue v){
|
||||
pMotor pMot = (pMotor)userData;
|
||||
SConnection *pCon = (SConnection *)callData;
|
||||
int status;
|
||||
|
||||
assert(pMot != NULL && pCon != NULL);
|
||||
status = MotorSetPar(pMot,pCon,currentNode->name, (float)v.v.doubleValue);
|
||||
return status;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int MotorParGetCallback(void *userData, void *callData,
|
||||
pHdb currentNode, hdbValue v){
|
||||
pMotor pMot = (pMotor)userData;
|
||||
float fVal;
|
||||
int status;
|
||||
|
||||
assert(pMot != NULL);
|
||||
status = MotorGetPar(pMot,currentNode->name,&fVal);
|
||||
currentNode->value.v.doubleValue = fVal;
|
||||
return status;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static pHdb MakeMotParNode(char *name, pMotor pMot){
|
||||
pHdb node = NULL;
|
||||
pHdbCallback pCall = NULL;
|
||||
|
||||
node = MakeHipadabaNode(name, HIPFLOAT, 1);
|
||||
if(node != NULL) {
|
||||
pCall = MakeHipadabaCallback(MotorParSetCallback,pMot,NULL,-1,-1);
|
||||
if(pCall == NULL){
|
||||
return NULL;
|
||||
}
|
||||
AppendHipadabaCallback(node,HCBSET,pCall);
|
||||
pCall = MakeHipadabaCallback(MotorParGetCallback,pMot,NULL,-1,-1);
|
||||
if(pCall == NULL){
|
||||
return NULL;
|
||||
}
|
||||
AppendHipadabaCallback(node,HCBREAD,pCall);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static int AddStdMotorPar(pHdb motorNode, pMotor pMot){
|
||||
int i;
|
||||
pHdb parNode = NULL;
|
||||
char *addPar[] = {"position",
|
||||
"target",
|
||||
"hardlowerlim",
|
||||
"hardupperlim",
|
||||
NULL};
|
||||
|
||||
i = 0;
|
||||
while(addPar[i] != NULL){
|
||||
parNode = MakeMotParNode(addPar[i],pMot);
|
||||
if(parNode == NULL){
|
||||
return 0;
|
||||
}
|
||||
AddHipadabaChild(motorNode,parNode, NULL);
|
||||
i++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the parameters in the obpar array
|
||||
*/
|
||||
for(i = 0; i < MOTOBPARLENGTH; i++){
|
||||
parNode = MakeMotParNode(pMot->ParArray[i].name,pMot);
|
||||
if(parNode == NULL){
|
||||
return 0;
|
||||
}
|
||||
AddHipadabaChild(motorNode,parNode, NULL);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static char *getDriverParList(MotorDriver *pDriv){
|
||||
SConnection *pCon = NULL;
|
||||
pDynString list = NULL;
|
||||
char *listData = NULL;
|
||||
|
||||
if(pDriv->ListDriverPar != NULL){
|
||||
pCon = SCCreateDummyConnection(pServ->pSics);
|
||||
if(pCon == NULL){
|
||||
return NULL;
|
||||
}
|
||||
SCStartBuffering(pCon);
|
||||
pDriv->ListDriverPar(pDriv,"test.", pCon);
|
||||
list = SCEndBuffering(pCon);
|
||||
if(list != NULL){
|
||||
listData = strdup(GetCharArray(list));
|
||||
SCDeleteConnection(pCon);
|
||||
} else {
|
||||
listData = NULL;
|
||||
}
|
||||
return listData;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
extern char *trim(char *str);
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static char *extractName(char *line){
|
||||
char *name = NULL, *pEnd = NULL;
|
||||
|
||||
name = strchr(line,'.');
|
||||
assert(name != NULL);
|
||||
while(*name == '.'){
|
||||
name++;
|
||||
}
|
||||
pEnd = strchr(name,'=');
|
||||
assert(pEnd != NULL);
|
||||
*pEnd = '\0';
|
||||
return trim(name);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int CreateDriverParameters(pMotor pM, pHdb parent){
|
||||
char *listPtr = NULL, line[80], *pPtr, *name;
|
||||
pHdb node = NULL;
|
||||
|
||||
listPtr = getDriverParList(pM->pDriver);
|
||||
if(listPtr == NULL){
|
||||
/*
|
||||
* no driver parameters
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
pPtr = listPtr;
|
||||
while((pPtr = stptok(pPtr,line,79,"\n")) != NULL){
|
||||
name = extractName(line);
|
||||
node = MakeMotParNode(name,pM);
|
||||
if(node != NULL){
|
||||
AddHipadabaChild(parent,node,NULL);
|
||||
}
|
||||
}
|
||||
free(listPtr);
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static pHdb CreateMotorAdapter(char *name, pMotor pMot){
|
||||
pHdb result = NULL;
|
||||
commandContext comCom;
|
||||
|
||||
assert(pMot != NULL);
|
||||
|
||||
result = MakeSICSHdbDriv(name,usUser,pMot,HIPFLOAT);
|
||||
if(result == NULL){
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* We want to be notified when this motor drives around. Or
|
||||
* its parameters change.
|
||||
*/
|
||||
strncpy(comCom.deviceID,name,255);
|
||||
comCom.transID = -77;
|
||||
RegisterCallback(pMot->pCall,comCom, MOTDRIVE, MoveCallback,
|
||||
result,NULL);
|
||||
RegisterCallback(pMot->pCall,comCom, HDBVAL, MotorValueCallback,
|
||||
result,NULL);
|
||||
|
||||
if(!AddStdMotorPar(result,pMot)){
|
||||
DeleteHipadabaNode(result,NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!CreateDriverParameters(pMot,result)){
|
||||
DeleteHipadabaNode(result,NULL);
|
||||
return NULL;
|
||||
}
|
||||
result->protected = 1;
|
||||
|
||||
return result;
|
||||
}
|
||||
/*============== histogram memory ======================================*/
|
||||
static long totalSum(int *data, int length){
|
||||
long result = 0l;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < length; i++){
|
||||
result += data[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int HMDataGetCallback(void *userData, void *callData,
|
||||
pHdb currentNode, hdbValue v){
|
||||
pHistMem pHM = (pHistMem)userData;
|
||||
SConnection *pCon = (SConnection *)callData;
|
||||
long sum1, sum2;
|
||||
|
||||
assert(pHM != NULL);
|
||||
if(pCon == NULL){
|
||||
return 0;
|
||||
}
|
||||
sum1 = totalSum(currentNode->value.v.intArray, currentNode->value.arrayLength);
|
||||
currentNode->value.arrayLength = GetHistLength(pHM);
|
||||
currentNode->value.v.intArray = (int *)GetHistogramPointer(pHM,pCon);
|
||||
sum2 = totalSum(currentNode->value.v.intArray, currentNode->value.arrayLength);
|
||||
if(sum1 != sum2){
|
||||
UpdateHipadabaPar(currentNode,currentNode->value,NULL);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static pHdb MakeHMDataNode(pHistMem pHM, char *name){
|
||||
pHdb node = NULL;
|
||||
pHdbCallback pCall = NULL;
|
||||
|
||||
|
||||
node = MakeHipadabaNode(name,HIPINTVARAR,2);
|
||||
if(node == NULL){
|
||||
return NULL;
|
||||
}
|
||||
pCall = MakeHipadabaCallback(HMDataGetCallback,pHM,NULL,-1,-1);
|
||||
if(pCall == NULL){
|
||||
return NULL;
|
||||
}
|
||||
AppendHipadabaCallback(node,HCBREAD,pCall);
|
||||
AppendHipadabaCallback(node,HCBSET,MakeReadOnlyCallback());
|
||||
|
||||
return node;
|
||||
}
|
||||
/*================ SICS Variable ======================================*/
|
||||
static int SicsVarSetCallback(void *userData, void *callData,
|
||||
pHdb currentNode, hdbValue v){
|
||||
pSicsVariable pVar = (pSicsVariable)userData;
|
||||
SConnection *pCon = (SConnection *)callData;
|
||||
int userRights = usMugger;
|
||||
|
||||
assert(pVar != NULL);
|
||||
|
||||
if(pCon != NULL){
|
||||
userRights = SCGetRights(pCon);
|
||||
}
|
||||
switch(currentNode->value.dataType){
|
||||
case HIPINT:
|
||||
VarSetInt(pVar, v.v.intValue, userRights);
|
||||
break;
|
||||
case HIPFLOAT:
|
||||
VarSetFloat(pVar, (float)v.v.doubleValue, userRights);
|
||||
break;
|
||||
case HIPTEXT:
|
||||
VarSetText(pVar, v.v.text, userRights);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int ValueCallback(int iEvent, void *eventData, void *userData,
|
||||
commandContext cc){
|
||||
pSicsVariable pVar = (pSicsVariable)eventData;
|
||||
pHdb node = (pHdb)userData;
|
||||
hdbValue v;
|
||||
|
||||
if(iEvent == VALUECHANGE && pVar != NULL && node != NULL){
|
||||
switch(pVar->eType){
|
||||
case veInt:
|
||||
v = MakeHdbInt(pVar->iVal);
|
||||
break;
|
||||
case veFloat:
|
||||
v = MakeHdbFloat((double)pVar->fVal);
|
||||
break;
|
||||
case veText:
|
||||
v = MakeHdbText(pVar->text);
|
||||
break;
|
||||
}
|
||||
UpdateHipadabaPar(node,v,NULL);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static pHdb MakeSicsVarNode(pSicsVariable pVar, char *name){
|
||||
pHdb node = NULL;
|
||||
pHdbCallback pCall = NULL;
|
||||
commandContext comCom;
|
||||
int type;
|
||||
|
||||
switch(pVar->eType){
|
||||
case veInt:
|
||||
type = HIPINT;
|
||||
break;
|
||||
case veFloat:
|
||||
type = HIPFLOAT;
|
||||
break;
|
||||
case veText:
|
||||
type = HIPTEXT;
|
||||
break;
|
||||
}
|
||||
node = MakeHipadabaNode(name,type,1);
|
||||
if(node == NULL){
|
||||
return NULL;
|
||||
}
|
||||
pCall = MakeHipadabaCallback(SicsVarSetCallback,pVar,NULL,-1,-1);
|
||||
if(pCall == NULL){
|
||||
return NULL;
|
||||
}
|
||||
strncpy(comCom.deviceID,name,255);
|
||||
comCom.transID = -77;
|
||||
AppendHipadabaCallback(node,HCBSET,pCall);
|
||||
RegisterCallback(pVar->pCall,comCom, VALUECHANGE, ValueCallback,
|
||||
node,NULL);
|
||||
|
||||
node->protected = 1;
|
||||
return node;
|
||||
}
|
||||
/*============== interpreter function ==================================*/
|
||||
int SICSHdbAdapter(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
pHdb root = NULL;
|
||||
pHdb path = NULL;
|
||||
pHdb node = NULL;
|
||||
pMotor pMot = NULL;
|
||||
pHistMem pHM = NULL;
|
||||
CommandList *pCom = NULL;
|
||||
pIDrivable pDriv = NULL;
|
||||
pSicsVariable pVar = NULL;
|
||||
char buffer[512];
|
||||
|
||||
root = GetHipadabaRoot();
|
||||
assert(root != NULL);
|
||||
|
||||
if(!SCMatchRights(pCon,usMugger)){
|
||||
return 0;
|
||||
}
|
||||
if(argc < 4) {
|
||||
SCWrite(pCon,"ERROR: Insufficient number of arguments",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
path = GetHipadabaNode(root,argv[1]);
|
||||
if(path == NULL){
|
||||
SCWrite(pCon,"ERROR: path to attach object too not found",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* look for motors
|
||||
*/
|
||||
pMot = (pMotor)FindCommandData(pSics,argv[2],"Motor");
|
||||
if(pMot != NULL){
|
||||
node = CreateMotorAdapter(argv[3],pMot);
|
||||
if(node == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory creating motor node",eError);
|
||||
return 0;
|
||||
}
|
||||
AddHipadabaChild(path,node,pCon);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
* look for drivables
|
||||
*/
|
||||
pDriv = FindDrivable(pSics,argv[2]);
|
||||
pCom = FindCommand(pSics,argv[2]);
|
||||
if(pDriv != NULL && pCom != NULL && pCom->pData != NULL){
|
||||
node = MakeSICSHdbDriv(argv[3],usUser,pCom->pData,HIPFLOAT);
|
||||
if(node == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory creating drivable node",eError);
|
||||
return 0;
|
||||
}
|
||||
AddHipadabaChild(path,node,pCon);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* look for SICS Variables
|
||||
*/
|
||||
pVar = (pSicsVariable)FindCommandData(pSics,argv[2],"SicsVariable");
|
||||
if(pVar != NULL){
|
||||
node = MakeSicsVarNode(pVar,argv[3]);
|
||||
if(node == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory creating SICS variable node",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
AddHipadabaChild(path,node,pCon);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* look for histogram memories
|
||||
*/
|
||||
pHM = (pHistMem)FindCommandData(pSics,argv[2],"HistMem");
|
||||
if(pHM != NULL){
|
||||
node = MakeHMDataNode(pHM,argv[3]);
|
||||
if(node == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory creating HM node",eError);
|
||||
return 0;
|
||||
}
|
||||
AddHipadabaChild(path,node,pCon);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
|
||||
snprintf(buffer,511,
|
||||
"ERROR: attaching this type of object: %s at %s not implemented",
|
||||
argv[2], argv[1]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
return 0;
|
||||
}
|
23
sicshdbadapter.h
Normal file
23
sicshdbadapter.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Experience has shown that integrating existing SICS objects into the
|
||||
* Hierarchical Parameter Database (Hdb) is a difficult task without reworking
|
||||
* the complete SICS object model. Rather, it seems easier to adapt some
|
||||
* critical objects to the Hdb with some glue code. Following the facade or
|
||||
* adapter design pattern. This is the purpose of this module. For the moment
|
||||
* the external interface is only an interpreter function which will be used to
|
||||
* install suitable SICS objects into the Hdb tree and generates the necessary
|
||||
* adapters internally. This code can be used to adapt to:
|
||||
* - motors
|
||||
* - the data segment of histogram memories
|
||||
*
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, November 2006
|
||||
*/
|
||||
#ifndef SICSHDBADAPTER_H_
|
||||
#define SICSHDBADAPTER_H_
|
||||
|
||||
int SICSHdbAdapter(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
#endif /*SICSHDBADAPTER_H_*/
|
318
sicshipadaba.c
318
sicshipadaba.c
@ -6,19 +6,22 @@
|
||||
* copyright: GPL
|
||||
*
|
||||
* Mark Koennecke, June 2006
|
||||
*
|
||||
* Introduced notification on tree changes, Mark Koennecke, November 2006
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <sicshipadaba.h>
|
||||
#include <sicshdbadapter.h>
|
||||
#include "sicspoll.h"
|
||||
#include <lld.h>
|
||||
#include <stptok.h>
|
||||
|
||||
/*== there can be only hipadaba in SICS, some globals to care for that == */
|
||||
static pHdb root = NULL;
|
||||
static int scriptUpdate = -1;
|
||||
static hdbUpdateTask taskData;
|
||||
static pSicsPoll poller = NULL;
|
||||
/*=============== common callback functions used for SICS ===========================*/
|
||||
static int SICSCheckPermissionCallback(void *userData, void *callData, pHdb node,
|
||||
hdbValue v){
|
||||
@ -79,7 +82,7 @@ static int SICSReadOnlyCallback(void *userData, void *callData, pHdb node,
|
||||
return SICSCBRO;
|
||||
}
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
static pHdbCallback MakeReadOnlyCallback(){
|
||||
pHdbCallback MakeReadOnlyCallback(){
|
||||
return MakeHipadabaCallback(SICSReadOnlyCallback, NULL,NULL,-1,-1);
|
||||
}
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
@ -101,6 +104,7 @@ pHdbCallback MakeSICSDriveCallback(void *sicsObject){
|
||||
/*---------------------------------------------------------------------------------------*/
|
||||
static int SICSReadDriveCallback(void *userData, void *callData, pHdb node,
|
||||
hdbValue v){
|
||||
static SConnection *defCon = NULL;
|
||||
SConnection *pCon = NULL;
|
||||
pDummy dum = NULL;
|
||||
pIDrivable pDriv = NULL;
|
||||
@ -108,7 +112,11 @@ static int SICSReadDriveCallback(void *userData, void *callData, pHdb node,
|
||||
|
||||
pCon = (SConnection *)callData;
|
||||
dum = (pDummy)userData;
|
||||
assert(pCon != NULL && dum != NULL);
|
||||
assert(dum != NULL);
|
||||
|
||||
if(defCon == NULL){
|
||||
defCon = SCCreateDummyConnection(pServ->pSics);
|
||||
}
|
||||
|
||||
pDriv = dum->pDescriptor->GetInterface(dum,DRIVEID);
|
||||
assert(pDriv != NULL);
|
||||
@ -116,6 +124,12 @@ static int SICSReadDriveCallback(void *userData, void *callData, pHdb node,
|
||||
value = pDriv->GetValue(dum,pCon);
|
||||
node->value.v.doubleValue = (double)value;
|
||||
v.v.doubleValue = (double)value;
|
||||
} else {
|
||||
if(defCon != NULL){
|
||||
value = pDriv->GetValue(dum,defCon);
|
||||
node->value.v.doubleValue = (double)value;
|
||||
v.v.doubleValue = (double)value;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -172,6 +186,33 @@ pHdbCallback MakeNotifyCallback(SConnection *pCon, int id){
|
||||
cbInfo->context = SCGetContext(pCon);
|
||||
return MakeHipadabaCallback(SICSNotifyCallback, cbInfo,free,id,pCon->ident);
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int TreeChangeCallback(void *userData, void *callData, pHdb node,
|
||||
hdbValue v){
|
||||
char *path = NULL;
|
||||
char buffer[1024];
|
||||
HdbCBInfo *cbInfo = (HdbCBInfo *)userData;
|
||||
|
||||
if(cbInfo != NULL && cbInfo->pCon != NULL){
|
||||
path = GetHipadabaPath(node);
|
||||
snprintf(buffer,1023,"treechange = %s", path);
|
||||
SCWriteInContext(cbInfo->pCon,buffer,eEvent,cbInfo->context);
|
||||
free(path);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
pHdbCallback MakeTreeChangeCallback(SConnection *pCon, int id){
|
||||
HdbCBInfo *cbInfo = NULL;
|
||||
|
||||
cbInfo = malloc(sizeof(HdbCBInfo));
|
||||
if(cbInfo == NULL){
|
||||
return NULL;
|
||||
}
|
||||
cbInfo->pCon = pCon;
|
||||
cbInfo->context = SCGetContext(pCon);
|
||||
return MakeHipadabaCallback(TreeChangeCallback, cbInfo,free,id,pCon->ident);
|
||||
}
|
||||
/*----------------------------------------------------------------------------------------*/
|
||||
static int SICSScriptWriteCallback(void *userData, void *callData, pHdb node,
|
||||
hdbValue v){
|
||||
@ -527,14 +568,14 @@ pHdb MakeSICSHdbPar(char *name, int priv, hdbValue v){
|
||||
|
||||
pHcb = MakeCheckPermissionCallback(priv);
|
||||
if(pHcb == NULL){
|
||||
DeleteHipadabaNode(result);
|
||||
DeleteHipadabaNode(result,NULL);
|
||||
return NULL;
|
||||
}
|
||||
AppendHipadabaCallback(result,HCBSET,pHcb);
|
||||
|
||||
pHcb = MakeSetUpdateCallback();
|
||||
if(pHcb == NULL){
|
||||
DeleteHipadabaNode(result);
|
||||
DeleteHipadabaNode(result,NULL);
|
||||
return NULL;
|
||||
}
|
||||
AppendHipadabaCallback(result,HCBSET,pHcb);
|
||||
@ -559,21 +600,21 @@ pHdb MakeSICSHdbDriv(char *name, int priv, void *sicsObject, int dataType){
|
||||
|
||||
pHcb = MakeCheckPermissionCallback(priv);
|
||||
if(pHcb == NULL){
|
||||
DeleteHipadabaNode(result);
|
||||
DeleteHipadabaNode(result,NULL);
|
||||
return NULL;
|
||||
}
|
||||
AppendHipadabaCallback(result,HCBSET,pHcb);
|
||||
|
||||
pHcb = MakeSICSDriveCallback(sicsObject);
|
||||
if(pHcb == NULL){
|
||||
DeleteHipadabaNode(result);
|
||||
DeleteHipadabaNode(result,NULL);
|
||||
return NULL;
|
||||
}
|
||||
AppendHipadabaCallback(result,HCBSET,pHcb);
|
||||
|
||||
pHcb = MakeSICSReadDriveCallback(sicsObject);
|
||||
if(pHcb == NULL){
|
||||
DeleteHipadabaNode(result);
|
||||
DeleteHipadabaNode(result,NULL);
|
||||
return NULL;
|
||||
}
|
||||
AppendHipadabaCallback(result,HCBREAD,pHcb);
|
||||
@ -592,21 +633,21 @@ pHdb MakeSICSMemPar(char *name, int priv, float *address){
|
||||
|
||||
pHcb = MakeCheckPermissionCallback(priv);
|
||||
if(pHcb == NULL){
|
||||
DeleteHipadabaNode(result);
|
||||
DeleteHipadabaNode(result,NULL);
|
||||
return NULL;
|
||||
}
|
||||
AppendHipadabaCallback(result,HCBSET,pHcb);
|
||||
|
||||
pHcb = MakeMemSetCallback(address);
|
||||
if(pHcb == NULL){
|
||||
DeleteHipadabaNode(result);
|
||||
DeleteHipadabaNode(result,NULL);
|
||||
return NULL;
|
||||
}
|
||||
AppendHipadabaCallback(result,HCBSET,pHcb);
|
||||
|
||||
pHcb = MakeMemReadCallback(address);
|
||||
if(pHcb == NULL){
|
||||
DeleteHipadabaNode(result);
|
||||
DeleteHipadabaNode(result,NULL);
|
||||
return NULL;
|
||||
}
|
||||
AppendHipadabaCallback(result,HCBREAD,pHcb);
|
||||
@ -626,7 +667,7 @@ pHdb MakeSICSROPar(char *name, hdbValue v){
|
||||
|
||||
pHcb = MakeReadOnlyCallback();
|
||||
if(pHcb == NULL){
|
||||
DeleteHipadabaNode(result);
|
||||
DeleteHipadabaNode(result,NULL);
|
||||
return NULL;
|
||||
}
|
||||
AppendHipadabaCallback(result,HCBSET,pHcb);
|
||||
@ -647,21 +688,21 @@ pHdb MakeSICSScriptPar(char *name, char *setScript, char *readScript,
|
||||
|
||||
pHcb = MakeSICSWriteScriptCallback(setScript);
|
||||
if(pHcb == NULL){
|
||||
DeleteHipadabaNode(result);
|
||||
DeleteHipadabaNode(result,NULL);
|
||||
return NULL;
|
||||
}
|
||||
AppendHipadabaCallback(result,HCBSET,pHcb);
|
||||
|
||||
pHcb = MakeSICSReadScriptCallback(readScript);
|
||||
if(pHcb == NULL){
|
||||
DeleteHipadabaNode(result);
|
||||
DeleteHipadabaNode(result,NULL);
|
||||
return NULL;
|
||||
}
|
||||
AppendHipadabaCallback(result,HCBREAD,pHcb);
|
||||
/**
|
||||
* put into the list of nodes to check with the update task
|
||||
*/
|
||||
LLDnodeAppend(scriptUpdate,&result);
|
||||
/* LLDnodeAppend(scriptUpdate,&result); */
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -675,15 +716,12 @@ pHdb CreateSICSScriptPar(char *name, char *setScript, char *readScript,
|
||||
static void removeNodeFromUpdateList(pHdb node){
|
||||
pHdb current = NULL;
|
||||
int status;
|
||||
char *objName = NULL;
|
||||
|
||||
status = LLDnodePtr2First(scriptUpdate);
|
||||
while(status != 0){
|
||||
current = LLDnodePtr(scriptUpdate);
|
||||
if(current == node){
|
||||
LLDnodeDelete(scriptUpdate);
|
||||
return;
|
||||
}
|
||||
status = LLDnodePtr2Next(scriptUpdate);
|
||||
objName = GetHipadabaPath(node);
|
||||
if(objName != NULL){
|
||||
removePollObject(poller, objName);
|
||||
free(objName);
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
@ -693,6 +731,13 @@ static void SICSDeleteNodeData(pHdb node){
|
||||
if(node == NULL){
|
||||
return;
|
||||
}
|
||||
|
||||
removeNodeFromUpdateList(node);
|
||||
while(node->child != NULL){
|
||||
tmp = node->child;
|
||||
node->child = node->child->next;
|
||||
SICSDeleteNodeData(tmp);
|
||||
}
|
||||
DeleteCallbackChain(node->writeCallbacks);
|
||||
DeleteCallbackChain(node->updateCallbacks);
|
||||
DeleteCallbackChain(node->readCallbacks);
|
||||
@ -703,23 +748,17 @@ static void SICSDeleteNodeData(pHdb node){
|
||||
ReleaseHdbValue(&node->value);
|
||||
node->magic = 000000;
|
||||
|
||||
while(node->child != NULL){
|
||||
tmp = node->child;
|
||||
node->child = node->child->next;
|
||||
SICSDeleteNodeData(tmp);
|
||||
}
|
||||
removeNodeFromUpdateList(node);
|
||||
free(node);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void RemoveSICSPar(pHdb node){
|
||||
void RemoveSICSPar(pHdb node, void *callData){
|
||||
pHdb current = NULL, tmp = NULL;
|
||||
|
||||
if(node == NULL){
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveHdbNodeFromParent(node);
|
||||
RemoveHdbNodeFromParent(node,NULL);
|
||||
|
||||
SICSDeleteNodeData(node);
|
||||
}
|
||||
@ -731,7 +770,7 @@ int AddSICSHdbPar(pHdb node, char *name, int priv, hdbValue v){
|
||||
if(child == NULL){
|
||||
return 0;
|
||||
}
|
||||
AddHipadabaChild(node,child);
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
@ -742,7 +781,7 @@ int AddSICSHdbROPar(pHdb node, char *name, hdbValue v){
|
||||
if(child == NULL){
|
||||
return 0;
|
||||
}
|
||||
AddHipadabaChild(node,child);
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@ -763,25 +802,25 @@ int AddSICSHdbMemPar(pHdb node, char *name, int priv,
|
||||
|
||||
pHcb = MakeCheckPermissionCallback(priv);
|
||||
if(pHcb == NULL){
|
||||
DeleteHipadabaNode(child);
|
||||
DeleteHipadabaNode(child,NULL);
|
||||
return 0;
|
||||
}
|
||||
AppendHipadabaCallback(child,HCBSET,pHcb);
|
||||
|
||||
pHcb = MakeMemGenSetCallback(data);
|
||||
if(pHcb == NULL){
|
||||
DeleteHipadabaNode(child);
|
||||
DeleteHipadabaNode(child,NULL);
|
||||
return 0;
|
||||
}
|
||||
AppendHipadabaCallback(child,HCBSET,pHcb);
|
||||
|
||||
pHcb = MakeMemGenReadCallback(data);
|
||||
if(pHcb == NULL){
|
||||
DeleteHipadabaNode(child);
|
||||
DeleteHipadabaNode(child,NULL);
|
||||
return 0;
|
||||
}
|
||||
AppendHipadabaCallback(child,HCBREAD,pHcb);
|
||||
AddHipadabaChild(node,child);
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -887,13 +926,16 @@ int SICSHdbSetPar(void *obj, SConnection *pCon,
|
||||
int InstallSICSNotify(pHdb node, SConnection *pCon, int id, int recurse){
|
||||
pHdb currentChild = NULL;
|
||||
pHdbCallback noty = NULL;
|
||||
pHdbCallback treeChange = NULL;
|
||||
|
||||
treeChange = MakeTreeChangeCallback(pCon,id);
|
||||
noty = MakeNotifyCallback(pCon,id);
|
||||
if(noty == NULL){
|
||||
if(noty == NULL || treeChange == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory installing callback", eError);
|
||||
return 0;
|
||||
}
|
||||
AppendHipadabaCallback(node, HCBUPDATE, noty);
|
||||
AppendHipadabaCallback(node, HCBTREE, treeChange);
|
||||
|
||||
if(recurse == 1){
|
||||
currentChild = node->child;
|
||||
@ -1041,60 +1083,6 @@ void SaveSICSHipadaba(FILE *fd, pHdb node, char *prefix){
|
||||
currentChild = currentChild->next;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int SICSHipadabaTask(void *pData){
|
||||
pHdbUpdateTask self = NULL;
|
||||
hdbValue old, newValue;
|
||||
pHdb currentNode = NULL;
|
||||
int status;
|
||||
|
||||
self = (pHdbUpdateTask)pData;
|
||||
assert(self != NULL);
|
||||
|
||||
if(self->iEnd == 1){
|
||||
return 0;
|
||||
}
|
||||
if(LLDcheck(self->updateList) == LIST_EMPTY){
|
||||
return 1;
|
||||
}
|
||||
memset(&old,0,sizeof(hdbValue));
|
||||
memset(&newValue,0,sizeof(hdbValue));
|
||||
|
||||
currentNode = (pHdb)LLDnodePtr(self->updateList);
|
||||
|
||||
if(currentNode != NULL){
|
||||
old.dataType = currentNode->value.dataType;
|
||||
copyHdbValue(¤tNode->value,&old);
|
||||
if(GetHipadabaPar(currentNode,&newValue, self->pCon) == 1){
|
||||
if(!compareHdbValue(old,newValue)){
|
||||
UpdateHipadabaPar(currentNode,newValue,self->pCon);
|
||||
}
|
||||
}
|
||||
ReleaseHdbValue(&old);
|
||||
ReleaseHdbValue(&newValue);
|
||||
|
||||
}
|
||||
status = LLDnodePtr2Next(self->updateList);
|
||||
if(status == 0){
|
||||
LLDnodePtr2First(self->updateList);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void SICSHipadabaSignal(void *pData, int iSignal, void *pSigData){
|
||||
pHdbUpdateTask self = NULL;
|
||||
int *iInt;
|
||||
|
||||
self = (pHdbUpdateTask)pData;
|
||||
|
||||
if(iSignal == SICSINT){
|
||||
iInt = (int *)pSigData;
|
||||
if(*iInt == eEndServer){
|
||||
self->iEnd = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*================ value helpers ============================================*/
|
||||
pDynString formatValue(hdbValue v){
|
||||
pDynString result = NULL;
|
||||
@ -1162,8 +1150,10 @@ static char *getNextHdbNumber(char *pStart, char pNumber[80]){
|
||||
static int adjustDataLength(hdbValue *v, char *data){
|
||||
char number[80];
|
||||
int count = 0;
|
||||
char *pPtr = NULL;
|
||||
|
||||
while(getNextHdbNumber(data,number) != NULL){
|
||||
pPtr = data;
|
||||
while((pPtr = getNextHdbNumber(pPtr,number)) != NULL){
|
||||
count++;
|
||||
}
|
||||
if(count != v->arrayLength){
|
||||
@ -1315,6 +1305,7 @@ static int MakeHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
char *pPtr = NULL;
|
||||
pHdb parent = NULL;
|
||||
pHdb child = NULL;
|
||||
char buffer[512], buffer2[512];
|
||||
|
||||
if(!SCMatchRights(pCon,usMugger)){
|
||||
return 0;
|
||||
@ -1351,7 +1342,8 @@ static int MakeHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
}
|
||||
|
||||
/* split off last path element */
|
||||
pPtr = strrchr(argv[1],'/');
|
||||
strncpy(buffer,argv[1],511);
|
||||
pPtr = strrchr(buffer,'/');
|
||||
if(pPtr == NULL){
|
||||
SCWrite(pCon,"ERROR: invalid path specification",
|
||||
eError);
|
||||
@ -1362,10 +1354,12 @@ static int MakeHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
if(strlen(pPtr) < 1) {
|
||||
parent = root;
|
||||
} else {
|
||||
parent = GetHipadabaNode(root,argv[1]);
|
||||
parent = GetHipadabaNode(root,buffer);
|
||||
}
|
||||
if(parent == NULL){
|
||||
SCWrite(pCon,"ERROR: parent for new node does not exist",eError);
|
||||
snprintf(buffer2,512,"ERROR: parent %s for new node does not exist",
|
||||
buffer);
|
||||
SCWrite(pCon,buffer2,eError);
|
||||
return 0;
|
||||
}
|
||||
if(type != HIPNONE){
|
||||
@ -1378,7 +1372,7 @@ static int MakeHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
return 0;
|
||||
}
|
||||
|
||||
AddHipadabaChild(parent,child);
|
||||
AddHipadabaChild(parent,child,pCon);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
@ -1390,6 +1384,10 @@ static int MakeHdbScriptNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
pHdb parent = NULL;
|
||||
pHdb child = NULL;
|
||||
pHdb current = NULL;
|
||||
char *urgv[] = {"5", NULL};
|
||||
char driver[] = {"hdb"};
|
||||
char buffer[512], buffer2[512];
|
||||
|
||||
|
||||
if(!SCMatchRights(pCon,usMugger)){
|
||||
return 0;
|
||||
@ -1422,7 +1420,8 @@ static int MakeHdbScriptNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
}
|
||||
|
||||
/* split off last path element */
|
||||
pPtr = strrchr(argv[1],'/');
|
||||
strncpy(buffer,argv[1],511);
|
||||
pPtr = strrchr(buffer,'/');
|
||||
if(pPtr == NULL){
|
||||
SCWrite(pCon,"ERROR: invalid path specification",
|
||||
eError);
|
||||
@ -1433,10 +1432,12 @@ static int MakeHdbScriptNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
if(strlen(pPtr) < 1) {
|
||||
parent = root;
|
||||
} else {
|
||||
parent = GetHipadabaNode(root,argv[1]);
|
||||
parent = GetHipadabaNode(root,buffer);
|
||||
}
|
||||
if(parent == NULL){
|
||||
SCWrite(pCon,"ERROR: parent for new node does not exist",eError);
|
||||
snprintf(buffer2,512,"ERROR: parent %s for new node does not exist",
|
||||
buffer);
|
||||
SCWrite(pCon,buffer2,eError);
|
||||
return 0;
|
||||
}
|
||||
child = MakeSICSScriptPar(pPtr, argv[3], argv[2],
|
||||
@ -1446,11 +1447,32 @@ static int MakeHdbScriptNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
return 0;
|
||||
}
|
||||
|
||||
AddHipadabaChild(parent,child);
|
||||
AddHipadabaChild(parent,child,pCon);
|
||||
/*
|
||||
* have it polled automatically
|
||||
*/
|
||||
addPollObject(poller,pCon, GetHipadabaPath(child),driver,1,urgv);
|
||||
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------------*/
|
||||
static int isNodeProtected(pHdb node){
|
||||
pHdb current = NULL;
|
||||
|
||||
if(node->protected == 1){
|
||||
return 1;
|
||||
}
|
||||
current = node->child;
|
||||
while(current != NULL){
|
||||
if(isNodeProtected(current)){
|
||||
return 1;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------------*/
|
||||
static int DeleteHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
@ -1469,7 +1491,13 @@ static int DeleteHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
SCWrite(pCon,"ERROR: node to delete not found",eError);
|
||||
return 0;
|
||||
}
|
||||
RemoveSICSPar(killNode);
|
||||
if(isNodeProtected(killNode)){
|
||||
SCWrite(pCon,"ERROR: this node or one of its children is protected",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
RemoveSICSPar(killNode, pCon);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
@ -1927,7 +1955,7 @@ static int LinkHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
return 0;
|
||||
}
|
||||
|
||||
AddHipadabaChild(node,pDum->pDescriptor->parNode);
|
||||
AddHipadabaChild(node,pDum->pDescriptor->parNode,pCon);
|
||||
|
||||
if(argc > 3){
|
||||
if(pDum->pDescriptor->parNode->name != NULL){
|
||||
@ -1939,41 +1967,75 @@ static int LinkHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int ChainCallback(void *userData, void *callData, pHdb node,
|
||||
hdbValue v){
|
||||
pHdb slave = (pHdb)userData;
|
||||
hdbValue vv, old;
|
||||
|
||||
if(slave != NULL){
|
||||
old = slave->value;
|
||||
memset(&vv,0,sizeof(hdbValue));
|
||||
GetHipadabaPar(slave,&vv,callData);
|
||||
if(!compareHdbValue(old,vv)){
|
||||
UpdateHipadabaPar(slave, vv, callData);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int ChainHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
pHdb master = NULL, slave = NULL;
|
||||
char buffer[512];
|
||||
pHdbCallback kalle = NULL;
|
||||
|
||||
if(argc < 3) {
|
||||
SCWrite(pCon,"ERROR: insufficent number of arguments to hchain",
|
||||
eError);
|
||||
}
|
||||
if(!SCMatchRights(pCon,usMugger)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
slave = GetHipadabaNode(root,argv[1]);
|
||||
if(slave == NULL){
|
||||
snprintf(buffer,511,"ERROR: slave %s not found",argv[1]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
master = GetHipadabaNode(root,argv[2]);
|
||||
if(master == NULL){
|
||||
snprintf(buffer,511,"ERROR: master %s not found",argv[1]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
kalle = MakeHipadabaCallback(ChainCallback,slave, NULL, -1,-1);
|
||||
if(kalle == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory creating callback",eError);
|
||||
return 0;
|
||||
}
|
||||
AppendHipadabaCallback(master,HCBUPDATE, kalle);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void killSICSHipadaba(){
|
||||
if(root != NULL){
|
||||
DeleteHipadabaNode(root);
|
||||
DeleteHipadabaNode(root,NULL);
|
||||
}
|
||||
root = NULL;
|
||||
/**
|
||||
* children have already been removed when killing the
|
||||
* main tree
|
||||
*/
|
||||
if(scriptUpdate > 0 && LLDcheck(scriptUpdate) != LIST_EMPTY){
|
||||
LLDdelete(scriptUpdate);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int InstallSICSHipadaba(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
|
||||
root = MakeHipadabaNode("/",HIPNONE,0);
|
||||
scriptUpdate = LLDcreate(sizeof(void *));
|
||||
taskData.updateList = scriptUpdate;
|
||||
taskData.iEnd = 0;
|
||||
taskData.pCon = SCCreateDummyConnection(pSics);
|
||||
if(taskData.pCon == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory creating Hipadaba",eError);
|
||||
return 0;
|
||||
}
|
||||
TaskRegister(pServ->pTasker,
|
||||
SICSHipadabaTask,
|
||||
SICSHipadabaSignal,
|
||||
NULL,
|
||||
&taskData,1);
|
||||
|
||||
AddCommand(pSics,"hmake", MakeHdbNode, NULL, NULL);
|
||||
AddCommand(pSics,"hmakescript", MakeHdbScriptNode, NULL, NULL);
|
||||
AddCommand(pSics,"hattach", SICSHdbAdapter, NULL, NULL);
|
||||
AddCommand(pSics,"hdel", DeleteHdbNode, NULL, NULL);
|
||||
AddCommand(pSics,"hset", SetHdbNode, NULL, NULL);
|
||||
AddCommand(pSics,"hget", GetHdbNode, NULL, NULL);
|
||||
@ -1983,6 +2045,10 @@ int InstallSICSHipadaba(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
AddCommand(pSics,"hlink", LinkHdbNode, NULL, NULL);
|
||||
AddCommand(pSics,"hinfo", HdbNodeInfo, NULL, NULL);
|
||||
AddCommand(pSics,"hval", HdbNodeVal, NULL, NULL);
|
||||
AddCommand(pSics,"hchain", ChainHdbNode, NULL, NULL);
|
||||
|
||||
InstallSICSPoll(pCon,pSics,pData,argc,argv);
|
||||
poller = (pSicsPoll)FindCommandData(pSics,"sicspoll","SicsPoll");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -25,6 +25,11 @@ typedef struct {
|
||||
int iEnd;
|
||||
}hdbUpdateTask, *pHdbUpdateTask;
|
||||
/*======================== common callbacks =====================================*/
|
||||
/**
|
||||
* make a ReadOnly callback
|
||||
* @return a callback which disallows setting of a parameter.
|
||||
*/
|
||||
pHdbCallback MakeReadOnlyCallback();
|
||||
/**
|
||||
* make a callback which checks permissions. To be used on write
|
||||
* @param priv The privilege to check against
|
||||
@ -107,6 +112,13 @@ pHdbCallback MakeMemReadCallback(float *address);
|
||||
* @return a suitable callback for setting this parameter.
|
||||
*/
|
||||
pHdbCallback MakeMemSetCallback(float *address);
|
||||
/**
|
||||
* make a tree chnage callback
|
||||
* @param pCon The connection to notfy on tree chnages
|
||||
* @id The ID of this callback
|
||||
* @return a suitable callback for notififications about tree changes.
|
||||
*/
|
||||
pHdbCallback MakeTreeChangeCallback(SConnection *pCon, int id);
|
||||
/*======================== parameter creation ===================================*/
|
||||
/**
|
||||
* make a simple SICS hdb parameter. Setting it will call update immediately. Use
|
||||
@ -184,8 +196,9 @@ pHdb CreateSICSScriptPar(char *name, char *setScript, char *readScript,
|
||||
* normal DeletHipadabaNode, this function also takes care of
|
||||
* clearing scipted nodes out of the update tasks watch list.
|
||||
* @param node The node to delete
|
||||
* @param callData User data for the tree change callback
|
||||
*/
|
||||
void RemoveSICSPar(pHdb node);
|
||||
void RemoveSICSPar(pHdb node, void *callData);
|
||||
/*=============== Add par functions =======================================*/
|
||||
/**
|
||||
* add a new simple hdb parameter as child to node
|
||||
|
360
sicspoll.c
Normal file
360
sicspoll.c
Normal file
@ -0,0 +1,360 @@
|
||||
/**
|
||||
* This is a generalized polling module for SICS. With this module
|
||||
* SICS variables can be polled regulary for updates. For different types of
|
||||
* SICS variables different polling mechanisms are required. In order to cope with
|
||||
* this requirement a polling interface and different drivers are defined in the
|
||||
* sister module polldriv.h and polldriv.c. This module implements the interface
|
||||
* to configure polling and the SICS task to run polling.
|
||||
*
|
||||
* Copyright: see COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, November-December 2006
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <sics.h>
|
||||
#include <splitter.h>
|
||||
|
||||
#include "polldriv.h"
|
||||
#include "splitter.h"
|
||||
#include <sicspoll.h>
|
||||
#include "lld.h"
|
||||
|
||||
/*================== data structure =====================================*/
|
||||
static SConnection *defCon = NULL;
|
||||
|
||||
struct __SICSPOLL{
|
||||
pObjectDescriptor pDes;
|
||||
int pollList; /* list with polled objects */
|
||||
int listDirty; /* a flag to set when the list has been modified. This will
|
||||
cause the list polling task to go back to the start. */
|
||||
SConnection *pCon; /* connection to use for polling */
|
||||
int iEnd; /* flag ending this */
|
||||
int nPoll; /* how many to poll in one run */
|
||||
long taskID;
|
||||
};
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void killSicsPoll(void *data){
|
||||
pSicsPoll self = (pSicsPoll)data;
|
||||
int status;
|
||||
pPollDriv poll = NULL;
|
||||
|
||||
self->iEnd = 1;
|
||||
status = LLDnodePtr2First(self->pollList);
|
||||
while(status != 0){
|
||||
poll = LLDnodePtr(self->pollList);
|
||||
if(poll != NULL){
|
||||
deletePollDriv(poll);
|
||||
}
|
||||
status = LLDnodePtr2Next(self->pollList);
|
||||
}
|
||||
LLDdelete(self->pollList);
|
||||
free(self);
|
||||
if(defCon != NULL){
|
||||
SCDeleteConnection(defCon);
|
||||
}
|
||||
}
|
||||
/*----------------- list access -----------------------------------------*/
|
||||
static pPollDriv locateObject(int list, char *objectIdentifier){
|
||||
int status;
|
||||
pPollDriv data = NULL;
|
||||
|
||||
status = LLDnodePtr2First(list);
|
||||
while(status != 0){
|
||||
data = (pPollDriv)LLDnodePtr(list);
|
||||
if(data != NULL){
|
||||
if(strcmp(data->objectIdentifier,objectIdentifier) == 0){
|
||||
return data;
|
||||
}
|
||||
}
|
||||
status = LLDnodePtr2Next(list);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*===================== task function ==================================*/
|
||||
static int incrList(int list){
|
||||
int status;
|
||||
|
||||
if(LLDcheck(list) == LIST_EMPTY){
|
||||
return 0;
|
||||
}
|
||||
status = LLDnodePtr2Next(list);
|
||||
if(status == 0) {
|
||||
status = LLDnodePtr2First(list);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void SicsPollSignal(void *pData, int iSignal, void *pSigData){
|
||||
pSicsPoll self = NULL;
|
||||
int *iInt;
|
||||
|
||||
self = (pSicsPoll)pData;
|
||||
|
||||
if(iSignal == SICSINT){
|
||||
iInt = (int *)pSigData;
|
||||
if(*iInt == eEndServer){
|
||||
self->iEnd = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int PollTask(void *data){
|
||||
pSicsPoll self = (pSicsPoll) data;
|
||||
pPollDriv poll = NULL;
|
||||
int status, i;
|
||||
time_t now = time(NULL);
|
||||
|
||||
if(self == NULL || self->iEnd == 1){
|
||||
return 0;
|
||||
}
|
||||
if(LLDcheck(self->pollList) == LIST_EMPTY){
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* increment list
|
||||
*/
|
||||
if(self->listDirty == 1){
|
||||
self->listDirty = 0;
|
||||
status = LLDnodePtr2First(self->pollList);
|
||||
}
|
||||
|
||||
/*
|
||||
* actually do poll
|
||||
*/
|
||||
for(i = 0; i < self->nPoll; i++){
|
||||
status = incrList(self->pollList);
|
||||
poll = (pPollDriv)LLDnodePtr(self->pollList);
|
||||
if(status != 0 && poll != NULL){
|
||||
if(poll->isDue(poll,now,self->pCon)){
|
||||
poll->poll(poll,self->pCon);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*==================== interface functions ==============================*/
|
||||
int removePollObject(pSicsPoll self, char *objectIdentifier){
|
||||
pPollDriv target = NULL;
|
||||
|
||||
self->listDirty = 1;
|
||||
target = locateObject(self->pollList, objectIdentifier);
|
||||
if(target != NULL){
|
||||
LLDnodeDelete(self->pollList);
|
||||
deletePollDriv(target);
|
||||
return 1;
|
||||
} else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int addPollObject(SicsPoll *self, SConnection *pCon, char *objectIdentifier,
|
||||
char *driver, int argc, char *argv[]){
|
||||
int status;
|
||||
pPollDriv driv = NULL;
|
||||
|
||||
driv = makePollDriver(pCon, driver,objectIdentifier,
|
||||
argc,argv);
|
||||
if(driv == NULL){
|
||||
return 0;
|
||||
}
|
||||
|
||||
LLDnodeAppend(self->pollList,&driv);
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static void printPollList(pSicsPoll self, SConnection *pCon){
|
||||
int status;
|
||||
pPollDriv driv = NULL;
|
||||
char buffer[512];
|
||||
|
||||
status = LLDnodePtr2First(self->pollList);
|
||||
while(status != 0){
|
||||
driv = (pPollDriv)LLDnodePtr(self->pollList);
|
||||
if(driv != NULL){
|
||||
snprintf(buffer,512,"%60s %3d",
|
||||
driv->objectIdentifier, driv->pollIntervall);
|
||||
SCWrite(pCon,buffer,eValue);
|
||||
}
|
||||
status = LLDnodePtr2Next(self->pollList);
|
||||
}
|
||||
}
|
||||
/*================== interpreter interface ===============================*/
|
||||
int SICSPollWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
pSicsPoll self = (pSicsPoll)pData;
|
||||
pPollDriv driv = NULL;
|
||||
int status, iVal;
|
||||
char buffer[512];
|
||||
pDynString txt = NULL;
|
||||
|
||||
assert(self != NULL);
|
||||
if(argc < 2){
|
||||
SCWrite(pCon,"ERROR: Not enough arguments",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
strtolower(argv[1]);
|
||||
if(strcmp(argv[1],"del") == 0) {
|
||||
if(argc < 3){
|
||||
SCWrite(pCon,"ERROR: Not enough arguments",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!SCMatchRights(pCon,usMugger)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
status = removePollObject(self,argv[2]);
|
||||
if(status == 0) {
|
||||
SCWrite(pCon,"ERROR: object to remove from poll list not found",eError);
|
||||
return 0;
|
||||
} else {
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
} else if(strcmp(argv[1],"add") == 0) {
|
||||
if(argc < 4){
|
||||
SCWrite(pCon,"ERROR: Not enough arguments",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!SCMatchRights(pCon,usMugger)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
driv = makePollDriver(pCon,argv[3], argv[2],
|
||||
argc-3, &argv[4]);
|
||||
if(driv != NULL){
|
||||
LLDnodeAppend(self->pollList,&driv);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else if (strcmp(argv[1],"npoll") == 0) {
|
||||
if(argc < 3) {
|
||||
snprintf(buffer,512,"%s.%s = %d", argv[0], "npoll", self->nPoll);
|
||||
} else {
|
||||
if(!SCMatchRights(pCon,usMugger)){
|
||||
return 0;
|
||||
}
|
||||
status = sscanf(argv[2],"%d",&self->nPoll);
|
||||
if(status != 1) {
|
||||
snprintf(buffer,512,"ERROR: failed to convert %s to int",argv[2]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
return 0;
|
||||
} else {
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} else if (strcmp(argv[1],"listen") == 0) {
|
||||
self->pCon = pCon;
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else if (strcmp(argv[1],"unlisten") == 0) {
|
||||
self->pCon = defCon;
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else if (strcmp(argv[1],"intervall") == 0){
|
||||
if(argc < 3){
|
||||
SCWrite(pCon,"ERROR: Not enough arguments",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!SCMatchRights(pCon,usMugger)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
driv = locateObject(self->pollList,argv[2]);
|
||||
if(driv == NULL){
|
||||
SCWrite(pCon,"ERROR: object not in polling list",eError);
|
||||
return 0;
|
||||
}
|
||||
if(argc > 3){
|
||||
status = sscanf(argv[3],"%d", &iVal);
|
||||
if(status != 1){
|
||||
snprintf(buffer,511,"ERROR: failed to convert %s to int",
|
||||
argv[3]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
return 0;
|
||||
}
|
||||
if(iVal < 0) {
|
||||
SCWrite(pCon,"ERROR: new value for intervall out of range",eError);
|
||||
return 0;
|
||||
}
|
||||
driv->pollIntervall = iVal;
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else {
|
||||
snprintf(buffer,511,"%s.intervall = %d",driv->objectIdentifier,
|
||||
driv->pollIntervall);
|
||||
SCWrite(pCon,buffer,eValue);
|
||||
return 1;
|
||||
}
|
||||
} else if (strcmp(argv[1],"list") == 0) {
|
||||
SCStartBuffering(pCon);
|
||||
printPollList(self,pCon);
|
||||
txt = SCEndBuffering(pCon);
|
||||
if(txt != NULL){
|
||||
SCWrite(pCon,GetCharArray(txt),eValue);
|
||||
}
|
||||
return 1;
|
||||
} else if (strcmp(argv[1],"poll") == 0) {
|
||||
if(argc < 3){
|
||||
SCWrite(pCon,"ERROR: Not enough arguments",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
driv = locateObject(self->pollList,argv[2]);
|
||||
if(driv == NULL){
|
||||
SCWrite(pCon,"ERROR: object not in polling list",eError);
|
||||
return 0;
|
||||
}
|
||||
status = driv->poll(driv,pCon);
|
||||
if(status != 1){
|
||||
SCWrite(pCon,"ERROR: polling object",eError);
|
||||
return 0;
|
||||
}
|
||||
SCWrite(pCon,"Object polled OK",eError);
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int InstallSICSPoll(SConnection *pCon,SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
pSicsPoll pNew = NULL;
|
||||
|
||||
pNew = malloc(sizeof(SicsPoll));
|
||||
if(pNew == NULL){
|
||||
return 0;
|
||||
}
|
||||
memset(pNew,0,sizeof(SicsPoll));
|
||||
|
||||
pNew->pDes = CreateDescriptor("SicsPoll");
|
||||
pNew->pollList = LLDcreate(sizeof(void *));
|
||||
defCon = SCCreateDummyConnection(pSics);
|
||||
|
||||
if(pNew->pDes == NULL|| pNew->pollList < 0 || defCon == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory creating SicsPoll",eError);
|
||||
return 0;
|
||||
}
|
||||
pNew->pCon = defCon;
|
||||
pNew->nPoll = 3;
|
||||
|
||||
TaskRegister(pServ->pTasker,PollTask,SicsPollSignal,NULL,pNew, 10);
|
||||
|
||||
if(argc > 1){
|
||||
AddCommand(pSics,argv[1],SICSPollWrapper,
|
||||
killSicsPoll,pNew);
|
||||
} else {
|
||||
AddCommand(pSics,"sicspoll",SICSPollWrapper,
|
||||
killSicsPoll,pNew);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
53
sicspoll.h
Normal file
53
sicspoll.h
Normal file
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* This is a generalized polling module for SICS. With this module
|
||||
* SICS variables can be polled regulary for updates. For different types of
|
||||
* SICS variables different polling mechanisms are required. In order to cope with
|
||||
* this requirement a polling interface and different drivers are defined in the
|
||||
* sister module polldriv.h and polldriv.c. This module implements the interface
|
||||
* to configure polling and the SICS task to run polling.
|
||||
*
|
||||
* Copyright: see COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, November-December 2006
|
||||
*/
|
||||
#ifndef SICSPOLL_H_
|
||||
#define SICSPOLL_H_
|
||||
/*=================== interpreter interface ================================*/
|
||||
/**
|
||||
* the factory function
|
||||
*/
|
||||
int InstallSICSPoll(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
/*
|
||||
* the actual wrapper which allows to configure and query the polling
|
||||
* module
|
||||
*/
|
||||
int SICSPollWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
/*================== Internal Interface ===================================*/
|
||||
typedef struct __SICSPOLL SicsPoll, *pSicsPoll;
|
||||
/**
|
||||
* add an object to the list of pollable objects.
|
||||
* @param self A pointer to a sicsPoll object managing the poll loop.
|
||||
* @param pCon a connection to report errors to
|
||||
* @param objectidentifier A string describing the object to poll.
|
||||
* This parameter will be used by the poll driver to locate the
|
||||
* pollable obejct.
|
||||
* @param The driver to use for polling
|
||||
* @param argc The number of additional parameters to pass to the
|
||||
* poll driver
|
||||
* @param argv[] The parameters to pass to the poll driver.
|
||||
* @return 1 on success or a negative error code when things go wrong.
|
||||
*/
|
||||
int addPollObject(SicsPoll *self, SConnection *pCon, char *objectIdentifier,
|
||||
char *driver, int argc, char *argv[]);
|
||||
/**
|
||||
* remove an object from the polling loop.
|
||||
* @param self A pointer to a sicsPoll object managing the poll loop.
|
||||
* @param objectIdentifier The identifier of the object to remove from
|
||||
* the poll loop.
|
||||
* @return 1 on success, a negative error code on failure.
|
||||
*/
|
||||
int removePollObject(SicsPoll *self, char *objectIdentifier);
|
||||
|
||||
#endif /*SICSPOLL_H_*/
|
306
sicspoll.tc
Normal file
306
sicspoll.tc
Normal file
@ -0,0 +1,306 @@
|
||||
/**
|
||||
* This is a generalized polling module for SICS. With this module
|
||||
* SICS variables can be polled regulary for updates. For different types of
|
||||
* SICS variables different polling mechanisms are required. In order to cope with
|
||||
* this requirement a polling interface and different drivers are defined in the
|
||||
* sister module polldriv.h and polldriv.c. This module implements the interface
|
||||
* to configure polling and the SICS task to run polling.
|
||||
*
|
||||
* Copyright: see COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, November-December 2006
|
||||
*/
|
||||
<%! source sicstemplates.tcl %>
|
||||
<% stdIncludes %>
|
||||
#include "polldriv.h"
|
||||
#include "splitter.h"
|
||||
#include <sicspoll.h>
|
||||
#include "lld.h"
|
||||
|
||||
/*================== data structure =====================================*/
|
||||
static SConnection *defCon = NULL;
|
||||
|
||||
struct __SICSPOLL{
|
||||
pObjectDescriptor pDes;
|
||||
int pollList; /* list with polled objects */
|
||||
int listDirty; /* a flag to set when the list has been modified. This will
|
||||
cause the list polling task to go back to the start. */
|
||||
SConnection *pCon; /* connection to use for polling */
|
||||
int iEnd; /* flag ending this */
|
||||
int nPoll; /* how many to poll in one run */
|
||||
long taskID;
|
||||
};
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void killSicsPoll(void *data){
|
||||
pSicsPoll self = (pSicsPoll)data;
|
||||
int status;
|
||||
pPollDriv poll = NULL;
|
||||
|
||||
self->iEnd = 1;
|
||||
status = LLDnodePtr2First(self->pollList);
|
||||
while(status != 0){
|
||||
poll = LLDnodePtr(self->pollList);
|
||||
if(poll != NULL){
|
||||
deletePollDriv(poll);
|
||||
}
|
||||
status = LLDnodePtr2Next(self->pollList);
|
||||
}
|
||||
LLDdelete(self->pollList);
|
||||
free(self);
|
||||
if(defCon != NULL){
|
||||
SCDeleteConnection(defCon);
|
||||
}
|
||||
}
|
||||
/*----------------- list access -----------------------------------------*/
|
||||
static pPollDriv locateObject(int list, char *objectIdentifier){
|
||||
int status;
|
||||
pPollDriv data = NULL;
|
||||
|
||||
status = LLDnodePtr2First(list);
|
||||
while(status != 0){
|
||||
data = (pPollDriv)LLDnodePtr(list);
|
||||
if(data != NULL){
|
||||
if(strcmp(data->objectIdentifier,objectIdentifier) == 0){
|
||||
return data;
|
||||
}
|
||||
}
|
||||
status = LLDnodePtr2Next(list);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*===================== task function ==================================*/
|
||||
static int incrList(int list){
|
||||
int status;
|
||||
|
||||
if(LLDcheck(list) == LIST_EMPTY){
|
||||
return 0;
|
||||
}
|
||||
status = LLDnodePtr2Next(list);
|
||||
if(status == 0) {
|
||||
status = LLDnodePtr2First(list);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void SicsPollSignal(void *pData, int iSignal, void *pSigData){
|
||||
pSicsPoll self = NULL;
|
||||
int *iInt;
|
||||
|
||||
self = (pSicsPoll)pData;
|
||||
|
||||
if(iSignal == SICSINT){
|
||||
iInt = (int *)pSigData;
|
||||
if(*iInt == eEndServer){
|
||||
self->iEnd = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int PollTask(void *data){
|
||||
pSicsPoll self = (pSicsPoll) data;
|
||||
pPollDriv poll = NULL;
|
||||
int status, i;
|
||||
time_t now = time(NULL);
|
||||
|
||||
if(self == NULL || self->iEnd == 1){
|
||||
return 0;
|
||||
}
|
||||
if(LLDcheck(self->pollList) == LIST_EMPTY){
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* increment list
|
||||
*/
|
||||
if(self->listDirty == 1){
|
||||
self->listDirty = 0;
|
||||
status = LLDnodePtr2First(self->pollList);
|
||||
}
|
||||
|
||||
/*
|
||||
* actually do poll
|
||||
*/
|
||||
for(i = 0; i < self->nPoll; i++){
|
||||
status = incrList(self->pollList);
|
||||
poll = (pPollDriv)LLDnodePtr(self->pollList);
|
||||
if(status != 0 && poll != NULL){
|
||||
if(poll->isDue(poll,now,self->pCon)){
|
||||
poll->poll(poll,self->pCon);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*==================== interface functions ==============================*/
|
||||
int removePollObject(pSicsPoll self, char *objectIdentifier){
|
||||
pPollDriv target = NULL;
|
||||
|
||||
self->listDirty = 1;
|
||||
target = locateObject(self->pollList, objectIdentifier);
|
||||
if(target != NULL){
|
||||
LLDnodeDelete(self->pollList);
|
||||
deletePollDriv(target);
|
||||
return 1;
|
||||
} else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int addPollObject(SicsPoll *self, SConnection *pCon, char *objectIdentifier,
|
||||
char *driver, int argc, char *argv[]){
|
||||
int status;
|
||||
pPollDriv driv = NULL;
|
||||
|
||||
driv = makePollDriver(pCon, driver,objectIdentifier,
|
||||
argc,argv);
|
||||
if(driv == NULL){
|
||||
return 0;
|
||||
}
|
||||
|
||||
LLDnodeAppend(self->pollList,&driv);
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static void printPollList(pSicsPoll self, SConnection *pCon){
|
||||
int status;
|
||||
pPollDriv driv = NULL;
|
||||
char buffer[512];
|
||||
|
||||
status = LLDnodePtr2First(self->pollList);
|
||||
while(status != 0){
|
||||
driv = (pPollDriv)LLDnodePtr(self->pollList);
|
||||
if(driv != NULL){
|
||||
snprintf(buffer,512,"%60s %3d",
|
||||
driv->objectIdentifier, driv->pollIntervall);
|
||||
SCWrite(pCon,buffer,eValue);
|
||||
}
|
||||
status = LLDnodePtr2Next(self->pollList);
|
||||
}
|
||||
}
|
||||
/*================== interpreter interface ===============================*/
|
||||
<%makeSicsFunc SICSPollWrapper%>{
|
||||
pSicsPoll self = (pSicsPoll)pData;
|
||||
pPollDriv driv = NULL;
|
||||
int status, iVal;
|
||||
char buffer[512];
|
||||
pDynString txt = NULL;
|
||||
|
||||
assert(self != NULL);
|
||||
<%testNoPar 2 5%>
|
||||
strtolower(argv[1]);
|
||||
if(strcmp(argv[1],"del") == 0) {
|
||||
<%testNoPar 3 9%>
|
||||
<%testPriv usMugger 9%>
|
||||
status = removePollObject(self,argv[2]);
|
||||
if(status == 0) {
|
||||
SCWrite(pCon,"ERROR: object to remove from poll list not found",eError);
|
||||
return 0;
|
||||
} else {
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
} else if(strcmp(argv[1],"add") == 0) {
|
||||
<%testNoPar 4 9%>
|
||||
<%testPriv usMugger 9%>
|
||||
driv = makePollDriver(pCon,argv[3], argv[2],
|
||||
argc-3, &argv[4]);
|
||||
if(driv != NULL){
|
||||
LLDnodeAppend(self->pollList,&driv);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else if (strcmp(argv[1],"npoll") == 0) {
|
||||
<%# sicsPar name, c-name nargs priv type indent
|
||||
sicsPar npoll self->nPoll 3 usMugger int 9%>
|
||||
} else if (strcmp(argv[1],"listen") == 0) {
|
||||
self->pCon = pCon;
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else if (strcmp(argv[1],"unlisten") == 0) {
|
||||
self->pCon = defCon;
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else if (strcmp(argv[1],"intervall") == 0){
|
||||
<%testNoPar 3 9%>
|
||||
<%testPriv usMugger 9%>
|
||||
driv = locateObject(self->pollList,argv[2]);
|
||||
if(driv == NULL){
|
||||
SCWrite(pCon,"ERROR: object not in polling list",eError);
|
||||
return 0;
|
||||
}
|
||||
if(argc > 3){
|
||||
status = sscanf(argv[3],"%d", &iVal);
|
||||
if(status != 1){
|
||||
snprintf(buffer,511,"ERROR: failed to convert %s to int",
|
||||
argv[3]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
return 0;
|
||||
}
|
||||
if(iVal < 0) {
|
||||
SCWrite(pCon,"ERROR: new value for intervall out of range",eError);
|
||||
return 0;
|
||||
}
|
||||
driv->pollIntervall = iVal;
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else {
|
||||
snprintf(buffer,511,"%s.intervall = %d",driv->objectIdentifier,
|
||||
driv->pollIntervall);
|
||||
SCWrite(pCon,buffer,eValue);
|
||||
return 1;
|
||||
}
|
||||
} else if (strcmp(argv[1],"list") == 0) {
|
||||
SCStartBuffering(pCon);
|
||||
printPollList(self,pCon);
|
||||
txt = SCEndBuffering(pCon);
|
||||
if(txt != NULL){
|
||||
SCWrite(pCon,GetCharArray(txt),eValue);
|
||||
}
|
||||
return 1;
|
||||
} else if (strcmp(argv[1],"poll") == 0) {
|
||||
<%testNoPar 3 9%>
|
||||
driv = locateObject(self->pollList,argv[2]);
|
||||
if(driv == NULL){
|
||||
SCWrite(pCon,"ERROR: object not in polling list",eError);
|
||||
return 0;
|
||||
}
|
||||
status = driv->poll(driv,pCon);
|
||||
if(status != 1){
|
||||
SCWrite(pCon,"ERROR: polling object",eError);
|
||||
return 0;
|
||||
}
|
||||
SCWrite(pCon,"Object polled OK",eError);
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
<%makeSicsFunc InstallSICSPoll%>{
|
||||
pSicsPoll pNew = NULL;
|
||||
|
||||
<%newStrucRet SicsPoll 5 0%>
|
||||
pNew->pDes = CreateDescriptor("SicsPoll");
|
||||
pNew->pollList = LLDcreate(sizeof(void *));
|
||||
defCon = SCCreateDummyConnection(pSics);
|
||||
|
||||
if(pNew->pDes == NULL|| pNew->pollList < 0 || defCon == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory creating SicsPoll",eError);
|
||||
return 0;
|
||||
}
|
||||
pNew->pCon = defCon;
|
||||
pNew->nPoll = 3;
|
||||
|
||||
TaskRegister(pServ->pTasker,PollTask,SicsPollSignal,NULL,pNew, 10);
|
||||
|
||||
if(argc > 1){
|
||||
AddCommand(pSics,argv[1],SICSPollWrapper,
|
||||
killSicsPoll,pNew);
|
||||
} else {
|
||||
AddCommand(pSics,"sicspoll",SICSPollWrapper,
|
||||
killSicsPoll,pNew);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
23
splitter.c
23
splitter.c
@ -479,6 +479,29 @@ char *Arg2Tcl0(int argc, char *argv[], char *buffer, int buffersize, char *prepe
|
||||
char *Arg2Tcl(int argc, char *argv[], char *buffer, int buffersize) {
|
||||
return Arg2Tcl0(argc, argv, buffer, buffersize, NULL);
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
char *sicsNextNumber(char *pStart, char pNumber[80]){
|
||||
int charCount = 0;
|
||||
pNumber[0] = '\0';
|
||||
|
||||
/* advance to first digit */
|
||||
while(isspace(*pStart) && *pStart != '\0'){
|
||||
pStart++;
|
||||
}
|
||||
if(*pStart == '\0'){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* copy */
|
||||
while(!isspace(*pStart) && *pStart != '\0' && charCount < 78){
|
||||
pNumber[charCount] = *pStart;
|
||||
pStart++;
|
||||
charCount++;
|
||||
}
|
||||
pNumber[charCount] = '\0';
|
||||
return pStart;
|
||||
}
|
||||
|
||||
/*============================================================================
|
||||
|
||||
Testprogram, can be activated by defining MAIN
|
||||
|
@ -93,4 +93,10 @@ typedef struct _TokenEntry {
|
||||
If prepend is not NULL, its contents appear untreated before the args.
|
||||
A space is used as separator.
|
||||
!*/
|
||||
char *sicsNextNumber(char *pStart, char pNumber[80]);
|
||||
/*!
|
||||
This function reads the next number from the string in pStart.
|
||||
The number is put into pNumber, a pointer to the string after
|
||||
the number is returned or NULL whne the string is exhausted.
|
||||
!*/
|
||||
#endif
|
||||
|
8
tasub.c
8
tasub.c
@ -1610,9 +1610,13 @@ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
|
||||
|
||||
strtolower(argv[1]);
|
||||
if(strcmp(argv[1],"mono") == 0){
|
||||
return handleCrystalCommands(&self->machine.monochromator,pCon,argc,argv);
|
||||
status = handleCrystalCommands(&self->machine.monochromator,pCon,argc,argv);
|
||||
self->mustRecalculate = 1;
|
||||
return status;
|
||||
} else if(strcmp(argv[1],"ana") == 0){
|
||||
return handleCrystalCommands(&self->machine.analyzer,pCon,argc,argv);
|
||||
status = handleCrystalCommands(&self->machine.analyzer,pCon,argc,argv);
|
||||
self->mustRecalculate = 1;
|
||||
return status;
|
||||
}else if(strcmp(argv[1],"cell") == 0){
|
||||
if(argc > 2){
|
||||
return tasReadCell(pCon,self,argc,argv);
|
||||
|
Reference in New Issue
Block a user