- 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",
|
"BATCHAREA",
|
||||||
"BATCHEND",
|
"BATCHEND",
|
||||||
"DRIVSTAT",
|
"DRIVSTAT",
|
||||||
|
"STATUS",
|
||||||
|
"POSITION",
|
||||||
|
"HDBVAL",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
16
event.h
16
event.h
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
#line 89 "event.w"
|
#line 96 "event.w"
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
E V E N T
|
E V E N T
|
||||||
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
int Text2Event(char *pText);
|
int Text2Event(char *pText);
|
||||||
|
|
||||||
#line 102 "event.w"
|
#line 109 "event.w"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -42,14 +42,16 @@
|
|||||||
#define BATCHAREA 15
|
#define BATCHAREA 15
|
||||||
#define BATCHEND 16
|
#define BATCHEND 16
|
||||||
#define DRIVSTAT 17
|
#define DRIVSTAT 17
|
||||||
#define STATUS 18
|
#define STATUS 18
|
||||||
#define POSITION 19 /* Position event for motors - ffr */
|
#define POSITION 19
|
||||||
#line 104 "event.w"
|
#define HDBVAL 20
|
||||||
|
|
||||||
|
#line 111 "event.w"
|
||||||
|
|
||||||
|
|
||||||
/*--------------- Signals for the Signalfunction of each task ------------*/
|
/*--------------- Signals for the Signalfunction of each task ------------*/
|
||||||
|
|
||||||
#line 73 "event.w"
|
#line 80 "event.w"
|
||||||
|
|
||||||
#define SICSINT 300
|
#define SICSINT 300
|
||||||
#define SICSBROADCAST 301
|
#define SICSBROADCAST 301
|
||||||
@ -57,6 +59,6 @@
|
|||||||
#define TOKENRELEASE 303
|
#define TOKENRELEASE 303
|
||||||
#define COMLOG 304
|
#define COMLOG 304
|
||||||
|
|
||||||
#line 107 "event.w"
|
#line 114 "event.w"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -53,6 +53,9 @@ $\langle$VE {\footnotesize ?}$\rangle\equiv$
|
|||||||
\mbox{}\verb@#define BATCHAREA 15@\\
|
\mbox{}\verb@#define BATCHAREA 15@\\
|
||||||
\mbox{}\verb@#define BATCHEND 16@\\
|
\mbox{}\verb@#define BATCHEND 16@\\
|
||||||
\mbox{}\verb@#define DRIVSTAT 17@\\
|
\mbox{}\verb@#define DRIVSTAT 17@\\
|
||||||
|
\mbox{}\verb@#define STATUS 18@\\
|
||||||
|
\mbox{}\verb@#define POSITION 19@\\
|
||||||
|
\mbox{}\verb@#define HDBVAL 20@\\
|
||||||
\mbox{}\verb@@$\diamond$
|
\mbox{}\verb@@$\diamond$
|
||||||
\end{list}
|
\end{list}
|
||||||
\vspace{-1ex}
|
\vspace{-1ex}
|
||||||
@ -87,6 +90,10 @@ operation.
|
|||||||
\item[BATCHEND] signals the end of the batch buffers processing.
|
\item[BATCHEND] signals the end of the batch buffers processing.
|
||||||
\item[DRIVSTAT] signals a change in the status of a driving operation
|
\item[DRIVSTAT] signals a change in the status of a driving operation
|
||||||
(start, finished, fault)
|
(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}
|
\end{description}
|
||||||
|
|
||||||
Furthermore event contains system wide signal codes which are interpreted in
|
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 BATCHAREA 15
|
||||||
#define BATCHEND 16
|
#define BATCHEND 16
|
||||||
#define DRIVSTAT 17
|
#define DRIVSTAT 17
|
||||||
|
#define STATUS 18
|
||||||
|
#define POSITION 19
|
||||||
|
#define HDBVAL 20
|
||||||
@}
|
@}
|
||||||
\begin{description}
|
\begin{description}
|
||||||
\item[VALUECHANGE] This is a variable changing its value. As event data a pointer to the
|
\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[BATCHEND] signals the end of the batch buffers processing.
|
||||||
\item[DRIVSTAT] signals a change in the status of a driving operation
|
\item[DRIVSTAT] signals a change in the status of a driving operation
|
||||||
(start, finished, fault)
|
(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}
|
\end{description}
|
||||||
|
|
||||||
Furthermore event contains system wide signal codes which are interpreted in
|
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(command != NULL);
|
||||||
assert(par != NULL);
|
assert(par != NULL);
|
||||||
|
|
||||||
AddHipadabaChild(command->parameters,par);
|
AddHipadabaChild(command->parameters,par,NULL);
|
||||||
}
|
}
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
void KillHdbCommandList(pHdbCommand commandList){
|
void KillHdbCommandList(pHdbCommand commandList){
|
||||||
@ -79,7 +79,7 @@ void KillHdbCommandList(pHdbCommand commandList){
|
|||||||
free(current->name);
|
free(current->name);
|
||||||
}
|
}
|
||||||
if(current->parameters != NULL){
|
if(current->parameters != NULL){
|
||||||
DeleteHipadabaNode(current->parameters);
|
DeleteHipadabaNode(current->parameters,NULL);
|
||||||
}
|
}
|
||||||
free(current);
|
free(current);
|
||||||
current = next;
|
current = next;
|
||||||
|
65
hipadaba.c
65
hipadaba.c
@ -38,6 +38,7 @@ static void DeleteNodeData(pHdb node){
|
|||||||
DeleteCallbackChain(node->writeCallbacks);
|
DeleteCallbackChain(node->writeCallbacks);
|
||||||
DeleteCallbackChain(node->updateCallbacks);
|
DeleteCallbackChain(node->updateCallbacks);
|
||||||
DeleteCallbackChain(node->readCallbacks);
|
DeleteCallbackChain(node->readCallbacks);
|
||||||
|
DeleteCallbackChain(node->treeChangeCallbacks);
|
||||||
|
|
||||||
if(node->name != NULL){
|
if(node->name != NULL){
|
||||||
free(node->name);
|
free(node->name);
|
||||||
@ -52,8 +53,24 @@ static void DeleteNodeData(pHdb node){
|
|||||||
}
|
}
|
||||||
free(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 parent = NULL;
|
||||||
pHdb current = NULL;
|
pHdb current = NULL;
|
||||||
|
|
||||||
@ -68,6 +85,8 @@ void RemoveHdbNodeFromParent(pHdb node){
|
|||||||
current = current->next;
|
current = current->next;
|
||||||
}
|
}
|
||||||
current->next = current->next->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;
|
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)
|
char *hdbTrim(char *str)
|
||||||
{
|
{
|
||||||
@ -553,7 +556,7 @@ pHdb MakeHipadabaNode(char *name, int datatype, int length){
|
|||||||
return pNew;
|
return pNew;
|
||||||
}
|
}
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
void AddHipadabaChild(pHdb parent, pHdb child){
|
void AddHipadabaChild(pHdb parent, pHdb child, void *callData){
|
||||||
pHdb current = NULL, prev = NULL;
|
pHdb current = NULL, prev = NULL;
|
||||||
|
|
||||||
assert(parent != NULL);
|
assert(parent != NULL);
|
||||||
@ -577,16 +580,18 @@ void AddHipadabaChild(pHdb parent, pHdb child){
|
|||||||
child->next = NULL;
|
child->next = NULL;
|
||||||
prev->next = child;
|
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;
|
pHdb current = NULL, tmp = NULL;
|
||||||
|
|
||||||
if(node == NULL){
|
if(node == NULL){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveHdbNodeFromParent(node);
|
RemoveHdbNodeFromParent(node, callData);
|
||||||
|
|
||||||
DeleteNodeData(node);
|
DeleteNodeData(node);
|
||||||
}
|
}
|
||||||
@ -733,6 +738,14 @@ void AppendHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
|
|||||||
current = node->readCallbacks;
|
current = node->readCallbacks;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case HCBTREE:
|
||||||
|
if(node->treeChangeCallbacks == NULL){
|
||||||
|
node->treeChangeCallbacks = newCB;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
current = node->treeChangeCallbacks;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
@ -778,6 +791,16 @@ void PrependHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
|
|||||||
node->readCallbacks = newCB;
|
node->readCallbacks = newCB;
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
@ -790,6 +813,7 @@ void RemoveHipadabaCallback(pHdb root, int id){
|
|||||||
root->writeCallbacks = DeleteForID(root->writeCallbacks,id);
|
root->writeCallbacks = DeleteForID(root->writeCallbacks,id);
|
||||||
root->updateCallbacks = DeleteForID(root->updateCallbacks,id);
|
root->updateCallbacks = DeleteForID(root->updateCallbacks,id);
|
||||||
root->readCallbacks = DeleteForID(root->readCallbacks,id);
|
root->readCallbacks = DeleteForID(root->readCallbacks,id);
|
||||||
|
root->treeChangeCallbacks = DeleteForID(root->treeChangeCallbacks,id);
|
||||||
|
|
||||||
current = root->child;
|
current = root->child;
|
||||||
while(current != NULL){
|
while(current != NULL){
|
||||||
@ -804,6 +828,7 @@ void InternalRemoveHipadabaCallback(pHdb root, int internalID){
|
|||||||
root->writeCallbacks = DeleteForInternalID(root->writeCallbacks,internalID);
|
root->writeCallbacks = DeleteForInternalID(root->writeCallbacks,internalID);
|
||||||
root->updateCallbacks = DeleteForInternalID(root->updateCallbacks,internalID);
|
root->updateCallbacks = DeleteForInternalID(root->updateCallbacks,internalID);
|
||||||
root->readCallbacks = DeleteForInternalID(root->readCallbacks,internalID);
|
root->readCallbacks = DeleteForInternalID(root->readCallbacks,internalID);
|
||||||
|
root->treeChangeCallbacks = DeleteForInternalID(root->treeChangeCallbacks,internalID);
|
||||||
|
|
||||||
current = root->child;
|
current = root->child;
|
||||||
while(current != NULL){
|
while(current != NULL){
|
||||||
|
18
hipadaba.h
18
hipadaba.h
@ -20,6 +20,8 @@
|
|||||||
* copyright: GPL
|
* copyright: GPL
|
||||||
*
|
*
|
||||||
* Mark Koennecke, June 2006
|
* Mark Koennecke, June 2006
|
||||||
|
*
|
||||||
|
* Added treeChange callback, Mark Koennecke, November 2006
|
||||||
*/
|
*/
|
||||||
#ifndef HIPADABA
|
#ifndef HIPADABA
|
||||||
#define HIPADABA
|
#define HIPADABA
|
||||||
@ -38,6 +40,7 @@
|
|||||||
#define HCBSET 0
|
#define HCBSET 0
|
||||||
#define HCBUPDATE 1
|
#define HCBUPDATE 1
|
||||||
#define HCBREAD 2
|
#define HCBREAD 2
|
||||||
|
#define HCBTREE 3
|
||||||
/*--------- error codes */
|
/*--------- error codes */
|
||||||
#define HDBTYPEMISMATCH -7701
|
#define HDBTYPEMISMATCH -7701
|
||||||
#define HDBLENGTHMISMATCH -7702
|
#define HDBLENGTHMISMATCH -7702
|
||||||
@ -63,12 +66,14 @@ typedef struct __hipadaba {
|
|||||||
struct __hdbcallback *writeCallbacks;
|
struct __hdbcallback *writeCallbacks;
|
||||||
struct __hdbcallback *updateCallbacks;
|
struct __hdbcallback *updateCallbacks;
|
||||||
struct __hdbcallback *readCallbacks;
|
struct __hdbcallback *readCallbacks;
|
||||||
|
struct __hdbcallback *treeChangeCallbacks;
|
||||||
char *name;
|
char *name;
|
||||||
hdbValue value;
|
hdbValue value;
|
||||||
|
int protected;
|
||||||
}Hdb, *pHdb;
|
}Hdb, *pHdb;
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
typedef int (*hdbCallbackFunction)(void *userData, void *callData,
|
typedef int (*hdbCallbackFunction)(void *userData, void *callData,
|
||||||
pHdb currentNode, hdbValue v );
|
pHdb currentNode, hdbValue v);
|
||||||
typedef void (*killUserData)(void *data);
|
typedef void (*killUserData)(void *data);
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
typedef struct __hdbcallback {
|
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.
|
* add a child to a node at the end of the child list.
|
||||||
* @param parent The node to which to add the child
|
* @param parent The node to which to add the child
|
||||||
* @param child The node to add
|
* @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
|
* delete a hipadaba node and all its children
|
||||||
* @parma node The node to delete
|
* @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
|
* checks if a Hdb node is valid
|
||||||
* @param node The node to check
|
* @param node The node to check
|
||||||
@ -209,8 +216,9 @@ char *GetHipadabaPath(pHdb node);
|
|||||||
/**
|
/**
|
||||||
* removes a node from the parents child list.
|
* removes a node from the parents child list.
|
||||||
* @node the node to remove
|
* @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
|
* delete a callback chain
|
||||||
* @param root The callback chain to delete
|
* @param root The callback chain to delete
|
||||||
@ -300,7 +308,7 @@ int SetHdbPar(pHdb node, int dataType, void *data, int length,
|
|||||||
void *callData);
|
void *callData);
|
||||||
/**
|
/**
|
||||||
* Updates a hipadaba parameter. This does not cause an active parameter to
|
* 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.
|
* this parameter.
|
||||||
* @param node The node for which to set the parameter
|
* @param node The node for which to set the parameter
|
||||||
* param dataType The datatype the value ought to have
|
* 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)
|
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))
|
if(SCMatchRights(pCon,usMugger))
|
||||||
{
|
{
|
||||||
iRet = HistConfigure(self,pCon,pSics);
|
iRet = HistConfigure(self,pCon,pSics);
|
||||||
if(iRet)
|
if(iRet)
|
||||||
{
|
{
|
||||||
self->iInit = 1;
|
self->iInit = 1;
|
||||||
SCSendOK(pCon);
|
SCSendOK(pCon);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1362,6 +1368,31 @@ static int checkHMEnd(pHistMem self, char *text){
|
|||||||
}
|
}
|
||||||
return iRet;
|
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 */
|
else if(strcmp(argv[1],"get") == 0) /* get a histogram */
|
||||||
{
|
{
|
||||||
/* check parameters, first required: no of Hist */
|
/* check parameters, first required: no of Hist */
|
||||||
@ -1602,8 +1633,8 @@ static int checkHMEnd(pHistMem self, char *text){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(GetStatus() == eCounting)
|
if(GetStatus() == eCounting)
|
||||||
{
|
{
|
||||||
SCWrite(pCon,"ERROR: cannot modify timebinning while counting",
|
SCWrite(pCon,"ERROR: cannot modify timebinning while counting",
|
||||||
eError);
|
eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -183,6 +183,13 @@
|
|||||||
lData[ii-iStart] = iSetVal;
|
lData[ii-iStart] = iSetVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(iSet == 2)
|
||||||
|
{
|
||||||
|
for(ii = iStart; ii < iEnd; ii++)
|
||||||
|
{
|
||||||
|
lData[ii-iStart] = self->data->localBuffer[ii];
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for(ii = iStart; ii < iEnd; ii++)
|
for(ii = iStart; ii < iEnd; ii++)
|
||||||
@ -196,7 +203,7 @@
|
|||||||
static int SimSetHistogram(pHistDriver self, SConnection *pCon,
|
static int SimSetHistogram(pHistDriver self, SConnection *pCon,
|
||||||
int i, int iStart, int iEnd, HistInt *lData)
|
int i, int iStart, int iEnd, HistInt *lData)
|
||||||
{
|
{
|
||||||
iSet = 1;
|
iSet = 2;
|
||||||
iSetVal = lData[0];
|
iSetVal = lData[0];
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
50
hmdata.c
50
hmdata.c
@ -5,11 +5,15 @@
|
|||||||
copyright: see file COPYRIGHT
|
copyright: see file COPYRIGHT
|
||||||
|
|
||||||
Mark Koennecke, January 2003
|
Mark Koennecke, January 2003
|
||||||
|
|
||||||
|
Added loading HM data from file, Mark Koennecke, November 2006
|
||||||
-------------------------------------------------------------------------*/
|
-------------------------------------------------------------------------*/
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include "splitter.h"
|
||||||
#include "fortify.h"
|
#include "fortify.h"
|
||||||
#include "hmdata.h"
|
#include "hmdata.h"
|
||||||
#include "HistMem.h"
|
#include "HistMem.h"
|
||||||
@ -410,7 +414,7 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
|
|||||||
iStart[0], iEnd[0]);
|
iStart[0], iEnd[0]);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
/*
|
|
||||||
lSum = 0;
|
lSum = 0;
|
||||||
for(i = iStart[1]; i < iEnd[1]; i++){
|
for(i = iStart[1]; i < iEnd[1]; i++){
|
||||||
iIndex = i*self->iDim[0];
|
iIndex = i*self->iDim[0];
|
||||||
@ -418,7 +422,8 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
|
|||||||
iIndex+iStart[0], iIndex+iEnd[0]);
|
iIndex+iStart[0], iIndex+iEnd[0]);
|
||||||
lSum += lRowSum;
|
lSum += lRowSum;
|
||||||
}
|
}
|
||||||
*/
|
/*
|
||||||
|
* This is wrong, see the bit about x and y somewhere
|
||||||
lSum = 0;
|
lSum = 0;
|
||||||
for(i = iStart[0]; i < iEnd[0]; i++){
|
for(i = iStart[0]; i < iEnd[0]; i++){
|
||||||
iIndex = i*self->iDim[1];
|
iIndex = i*self->iDim[1];
|
||||||
@ -426,6 +431,7 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
|
|||||||
iIndex+iStart[1], iIndex+iEnd[1]);
|
iIndex+iStart[1], iIndex+iEnd[1]);
|
||||||
lSum += lRowSum;
|
lSum += lRowSum;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sprintf(pBueffel,
|
sprintf(pBueffel,
|
||||||
@ -440,3 +446,43 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
|
|||||||
}
|
}
|
||||||
return lSum;
|
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,
|
long sumHMDataRectangle(pHistMem self, SConnection *pCon,
|
||||||
int start[MAXDIM], int end[MAXDIM]);
|
int start[MAXDIM], int end[MAXDIM]);
|
||||||
|
int loadHMData(pHMdata self, SConnection *pCon, char *filename);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#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,
|
long sumHMDataRectangle(pHistMem self, SConnection *pCon,
|
||||||
int start[MAXDIM], int end[MAXDIM]);
|
int start[MAXDIM], int end[MAXDIM]);
|
||||||
|
int loadHMData(pHMdata self, SConnection *pCon, char *filename);
|
||||||
@}
|
@}
|
||||||
|
|
||||||
\begin{description}
|
\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!
|
pointer of HMdata. Use with extra care!
|
||||||
\item[sumHMDataRectangle] sums a rectangular box delimted by start and end
|
\item[sumHMDataRectangle] sums a rectangular box delimted by start and end
|
||||||
from the histogram memory.
|
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}
|
\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 \
|
hmdata.o nxscript.o tclintimpl.o sicsdata.o mcstascounter.o \
|
||||||
mcstashm.o initializer.o remob.o tclmotdriv.o protocol.o \
|
mcstashm.o initializer.o remob.o tclmotdriv.o protocol.o \
|
||||||
sinfox.o sicslist.o cone.o hipadaba.o sicshipadaba.o statistics.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
|
MOTOROBJ = motor.o simdriv.o
|
||||||
COUNTEROBJ = countdriv.o simcter.o counter.o
|
COUNTEROBJ = countdriv.o simcter.o counter.o
|
||||||
VELOOBJ = velo.o velosim.o
|
VELOOBJ = velo.o velosim.o
|
||||||
|
|
||||||
.SUFFIXES:
|
.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
|
all: libmat libhlib libtecsl libpsi SICServer
|
||||||
|
|
||||||
|
13
motor.c
13
motor.c
@ -76,13 +76,6 @@
|
|||||||
#define IGNOREFAULT 10
|
#define IGNOREFAULT 10
|
||||||
#define MOVECOUNT 11
|
#define MOVECOUNT 11
|
||||||
|
|
||||||
/*------------------------------------------------------------------------
|
|
||||||
a tiny structure used in CallBack work
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
float fVal;
|
|
||||||
char *pName;
|
|
||||||
} MotCallback;
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
static void *MotorGetInterface(void *pData, int iID)
|
static void *MotorGetInterface(void *pData, int iID)
|
||||||
@ -416,7 +409,7 @@ static void handleMoveCallback(pMotor self, SConnection *pCon)
|
|||||||
|
|
||||||
|
|
||||||
/* create and initialize parameters */
|
/* create and initialize parameters */
|
||||||
pM->ParArray = ObParCreate(12);
|
pM->ParArray = ObParCreate(MOTOBPARLENGTH);
|
||||||
if(!pM->ParArray)
|
if(!pM->ParArray)
|
||||||
{
|
{
|
||||||
free(pM);
|
free(pM);
|
||||||
@ -606,6 +599,7 @@ extern void KillPiPiezo(void *pData);
|
|||||||
if(iRet == 1)
|
if(iRet == 1)
|
||||||
{
|
{
|
||||||
SCparChange(pCon);
|
SCparChange(pCon);
|
||||||
|
InvokeCallBack(self->pCall,HDBVAL,self);
|
||||||
return iRet;
|
return iRet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -631,6 +625,7 @@ extern void KillPiPiezo(void *pData);
|
|||||||
fLimit -= fChange;
|
fLimit -= fChange;
|
||||||
ObParSet(self->ParArray,self->name,"softlowerlim",fLimit,pCon);
|
ObParSet(self->ParArray,self->name,"softlowerlim",fLimit,pCon);
|
||||||
SCparChange(pCon);
|
SCparChange(pCon);
|
||||||
|
InvokeCallBack(self->pCall,HDBVAL,self);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -652,6 +647,7 @@ extern void KillPiPiezo(void *pData);
|
|||||||
ObParInit(self->ParArray,SZERO,"softzero",ZEROINACTIVE,usUser);
|
ObParInit(self->ParArray,SZERO,"softzero",ZEROINACTIVE,usUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
InvokeCallBack(self->pCall,HDBVAL,self);
|
||||||
SCparChange(pCon);
|
SCparChange(pCon);
|
||||||
|
|
||||||
return iRet;
|
return iRet;
|
||||||
@ -785,6 +781,7 @@ extern void KillPiPiezo(void *pData);
|
|||||||
self->retryCount = 0;
|
self->retryCount = 0;
|
||||||
self->stopped = 0;
|
self->stopped = 0;
|
||||||
self->fTarget = fHard;
|
self->fTarget = fHard;
|
||||||
|
InvokeCallBack(self->pCall,HDBVAL,self);
|
||||||
self->posCount = 0;
|
self->posCount = 0;
|
||||||
iRet = self->pDriver->RunTo(self->pDriver,fHard);
|
iRet = self->pDriver->RunTo(self->pDriver,fHard);
|
||||||
if(iRet != OKOK)
|
if(iRet != OKOK)
|
||||||
|
8
motor.h
8
motor.h
@ -14,6 +14,7 @@
|
|||||||
#include "obdes.h"
|
#include "obdes.h"
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
|
|
||||||
|
#define MOTOBPARLENGTH 12
|
||||||
typedef struct __Motor {
|
typedef struct __Motor {
|
||||||
pObjectDescriptor pDescriptor;
|
pObjectDescriptor pDescriptor;
|
||||||
ObPar *ParArray;
|
ObPar *ParArray;
|
||||||
@ -32,6 +33,13 @@
|
|||||||
int stopped;
|
int stopped;
|
||||||
} Motor;
|
} Motor;
|
||||||
typedef Motor *pMotor;
|
typedef Motor *pMotor;
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
a tiny structure used in CallBack work
|
||||||
|
--------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
float fVal;
|
||||||
|
char *pName;
|
||||||
|
} MotCallback;
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/* parameter management */
|
/* 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 iRet, iStatus;
|
||||||
int iCount;
|
int iCount;
|
||||||
NetItem NItem;
|
NetItem NItem;
|
||||||
|
int conCount = 0;
|
||||||
|
char num[50];
|
||||||
|
IPair *options = NULL;
|
||||||
|
|
||||||
self = (pNetRead)pData;
|
self = (pNetRead)pData;
|
||||||
assert(self);
|
assert(self);
|
||||||
@ -716,9 +719,13 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
|
|||||||
{
|
{
|
||||||
iCount = NItem.pSock->sockid;
|
iCount = NItem.pSock->sockid;
|
||||||
}
|
}
|
||||||
|
conCount++;
|
||||||
iRet = LLDnodePtr2Next(self->iList);
|
iRet = LLDnodePtr2Next(self->iList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snprintf(num,50,"%d", conCount);
|
||||||
|
IFSetOption(pSICSOptions,"ConnectionCount",num);
|
||||||
|
|
||||||
/* the select itself */
|
/* the select itself */
|
||||||
tmo.tv_usec = self->iReadTimeout;
|
tmo.tv_usec = self->iReadTimeout;
|
||||||
iCount++;
|
iCount++;
|
||||||
|
@ -109,6 +109,8 @@
|
|||||||
/* initialise tasker */
|
/* initialise tasker */
|
||||||
assert(TaskerInit(&self->pTasker));
|
assert(TaskerInit(&self->pTasker));
|
||||||
|
|
||||||
|
pSICSOptions = IFAddOption(pSICSOptions, "ConnectionCount","0");
|
||||||
|
|
||||||
/* initialise the server from script */
|
/* initialise the server from script */
|
||||||
if(file == NULL)
|
if(file == NULL)
|
||||||
{
|
{
|
||||||
|
2
obdes.c
2
obdes.c
@ -84,7 +84,7 @@
|
|||||||
*/
|
*/
|
||||||
if(self->parNode != NULL){
|
if(self->parNode != NULL){
|
||||||
if(self->parNode->mama == NULL){
|
if(self->parNode->mama == NULL){
|
||||||
DeleteHipadabaNode(self->parNode);
|
DeleteHipadabaNode(self->parNode,NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(self);
|
free(self);
|
||||||
|
3
ofac.c
3
ofac.c
@ -120,6 +120,7 @@
|
|||||||
#include "cone.h"
|
#include "cone.h"
|
||||||
#include "sicshipadaba.h"
|
#include "sicshipadaba.h"
|
||||||
#include "multicounter.h"
|
#include "multicounter.h"
|
||||||
|
#include "sicspoll.h"
|
||||||
/*----------------------- Server options creation -------------------------*/
|
/*----------------------- Server options creation -------------------------*/
|
||||||
static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData,
|
static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[])
|
int argc, char *argv[])
|
||||||
@ -331,6 +332,8 @@
|
|||||||
MakeCone,NULL,NULL);
|
MakeCone,NULL,NULL);
|
||||||
AddCommand(pInter,"MakeMultiCounter",
|
AddCommand(pInter,"MakeMultiCounter",
|
||||||
MakeMultiCounter,NULL,NULL);
|
MakeMultiCounter,NULL,NULL);
|
||||||
|
AddCommand(pInter,"MakeSicsPoll",
|
||||||
|
InstallSICSPoll,NULL,NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
install site specific commands
|
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
|
* copyright: GPL
|
||||||
*
|
*
|
||||||
* Mark Koennecke, June 2006
|
* Mark Koennecke, June 2006
|
||||||
|
*
|
||||||
|
* Introduced notification on tree changes, Mark Koennecke, November 2006
|
||||||
*/
|
*/
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sicshipadaba.h>
|
#include <sicshipadaba.h>
|
||||||
|
#include <sicshdbadapter.h>
|
||||||
|
#include "sicspoll.h"
|
||||||
#include <lld.h>
|
#include <lld.h>
|
||||||
#include <stptok.h>
|
#include <stptok.h>
|
||||||
|
|
||||||
/*== there can be only hipadaba in SICS, some globals to care for that == */
|
/*== there can be only hipadaba in SICS, some globals to care for that == */
|
||||||
static pHdb root = NULL;
|
static pHdb root = NULL;
|
||||||
static int scriptUpdate = -1;
|
static pSicsPoll poller = NULL;
|
||||||
static hdbUpdateTask taskData;
|
|
||||||
/*=============== common callback functions used for SICS ===========================*/
|
/*=============== common callback functions used for SICS ===========================*/
|
||||||
static int SICSCheckPermissionCallback(void *userData, void *callData, pHdb node,
|
static int SICSCheckPermissionCallback(void *userData, void *callData, pHdb node,
|
||||||
hdbValue v){
|
hdbValue v){
|
||||||
@ -79,7 +82,7 @@ static int SICSReadOnlyCallback(void *userData, void *callData, pHdb node,
|
|||||||
return SICSCBRO;
|
return SICSCBRO;
|
||||||
}
|
}
|
||||||
/*-------------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------------*/
|
||||||
static pHdbCallback MakeReadOnlyCallback(){
|
pHdbCallback MakeReadOnlyCallback(){
|
||||||
return MakeHipadabaCallback(SICSReadOnlyCallback, NULL,NULL,-1,-1);
|
return MakeHipadabaCallback(SICSReadOnlyCallback, NULL,NULL,-1,-1);
|
||||||
}
|
}
|
||||||
/*-------------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------------*/
|
||||||
@ -101,6 +104,7 @@ pHdbCallback MakeSICSDriveCallback(void *sicsObject){
|
|||||||
/*---------------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------------*/
|
||||||
static int SICSReadDriveCallback(void *userData, void *callData, pHdb node,
|
static int SICSReadDriveCallback(void *userData, void *callData, pHdb node,
|
||||||
hdbValue v){
|
hdbValue v){
|
||||||
|
static SConnection *defCon = NULL;
|
||||||
SConnection *pCon = NULL;
|
SConnection *pCon = NULL;
|
||||||
pDummy dum = NULL;
|
pDummy dum = NULL;
|
||||||
pIDrivable pDriv = NULL;
|
pIDrivable pDriv = NULL;
|
||||||
@ -108,7 +112,11 @@ static int SICSReadDriveCallback(void *userData, void *callData, pHdb node,
|
|||||||
|
|
||||||
pCon = (SConnection *)callData;
|
pCon = (SConnection *)callData;
|
||||||
dum = (pDummy)userData;
|
dum = (pDummy)userData;
|
||||||
assert(pCon != NULL && dum != NULL);
|
assert(dum != NULL);
|
||||||
|
|
||||||
|
if(defCon == NULL){
|
||||||
|
defCon = SCCreateDummyConnection(pServ->pSics);
|
||||||
|
}
|
||||||
|
|
||||||
pDriv = dum->pDescriptor->GetInterface(dum,DRIVEID);
|
pDriv = dum->pDescriptor->GetInterface(dum,DRIVEID);
|
||||||
assert(pDriv != NULL);
|
assert(pDriv != NULL);
|
||||||
@ -116,6 +124,12 @@ static int SICSReadDriveCallback(void *userData, void *callData, pHdb node,
|
|||||||
value = pDriv->GetValue(dum,pCon);
|
value = pDriv->GetValue(dum,pCon);
|
||||||
node->value.v.doubleValue = (double)value;
|
node->value.v.doubleValue = (double)value;
|
||||||
v.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;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -172,6 +186,33 @@ pHdbCallback MakeNotifyCallback(SConnection *pCon, int id){
|
|||||||
cbInfo->context = SCGetContext(pCon);
|
cbInfo->context = SCGetContext(pCon);
|
||||||
return MakeHipadabaCallback(SICSNotifyCallback, cbInfo,free,id,pCon->ident);
|
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,
|
static int SICSScriptWriteCallback(void *userData, void *callData, pHdb node,
|
||||||
hdbValue v){
|
hdbValue v){
|
||||||
@ -527,14 +568,14 @@ pHdb MakeSICSHdbPar(char *name, int priv, hdbValue v){
|
|||||||
|
|
||||||
pHcb = MakeCheckPermissionCallback(priv);
|
pHcb = MakeCheckPermissionCallback(priv);
|
||||||
if(pHcb == NULL){
|
if(pHcb == NULL){
|
||||||
DeleteHipadabaNode(result);
|
DeleteHipadabaNode(result,NULL);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
AppendHipadabaCallback(result,HCBSET,pHcb);
|
AppendHipadabaCallback(result,HCBSET,pHcb);
|
||||||
|
|
||||||
pHcb = MakeSetUpdateCallback();
|
pHcb = MakeSetUpdateCallback();
|
||||||
if(pHcb == NULL){
|
if(pHcb == NULL){
|
||||||
DeleteHipadabaNode(result);
|
DeleteHipadabaNode(result,NULL);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
AppendHipadabaCallback(result,HCBSET,pHcb);
|
AppendHipadabaCallback(result,HCBSET,pHcb);
|
||||||
@ -559,21 +600,21 @@ pHdb MakeSICSHdbDriv(char *name, int priv, void *sicsObject, int dataType){
|
|||||||
|
|
||||||
pHcb = MakeCheckPermissionCallback(priv);
|
pHcb = MakeCheckPermissionCallback(priv);
|
||||||
if(pHcb == NULL){
|
if(pHcb == NULL){
|
||||||
DeleteHipadabaNode(result);
|
DeleteHipadabaNode(result,NULL);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
AppendHipadabaCallback(result,HCBSET,pHcb);
|
AppendHipadabaCallback(result,HCBSET,pHcb);
|
||||||
|
|
||||||
pHcb = MakeSICSDriveCallback(sicsObject);
|
pHcb = MakeSICSDriveCallback(sicsObject);
|
||||||
if(pHcb == NULL){
|
if(pHcb == NULL){
|
||||||
DeleteHipadabaNode(result);
|
DeleteHipadabaNode(result,NULL);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
AppendHipadabaCallback(result,HCBSET,pHcb);
|
AppendHipadabaCallback(result,HCBSET,pHcb);
|
||||||
|
|
||||||
pHcb = MakeSICSReadDriveCallback(sicsObject);
|
pHcb = MakeSICSReadDriveCallback(sicsObject);
|
||||||
if(pHcb == NULL){
|
if(pHcb == NULL){
|
||||||
DeleteHipadabaNode(result);
|
DeleteHipadabaNode(result,NULL);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
AppendHipadabaCallback(result,HCBREAD,pHcb);
|
AppendHipadabaCallback(result,HCBREAD,pHcb);
|
||||||
@ -592,21 +633,21 @@ pHdb MakeSICSMemPar(char *name, int priv, float *address){
|
|||||||
|
|
||||||
pHcb = MakeCheckPermissionCallback(priv);
|
pHcb = MakeCheckPermissionCallback(priv);
|
||||||
if(pHcb == NULL){
|
if(pHcb == NULL){
|
||||||
DeleteHipadabaNode(result);
|
DeleteHipadabaNode(result,NULL);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
AppendHipadabaCallback(result,HCBSET,pHcb);
|
AppendHipadabaCallback(result,HCBSET,pHcb);
|
||||||
|
|
||||||
pHcb = MakeMemSetCallback(address);
|
pHcb = MakeMemSetCallback(address);
|
||||||
if(pHcb == NULL){
|
if(pHcb == NULL){
|
||||||
DeleteHipadabaNode(result);
|
DeleteHipadabaNode(result,NULL);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
AppendHipadabaCallback(result,HCBSET,pHcb);
|
AppendHipadabaCallback(result,HCBSET,pHcb);
|
||||||
|
|
||||||
pHcb = MakeMemReadCallback(address);
|
pHcb = MakeMemReadCallback(address);
|
||||||
if(pHcb == NULL){
|
if(pHcb == NULL){
|
||||||
DeleteHipadabaNode(result);
|
DeleteHipadabaNode(result,NULL);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
AppendHipadabaCallback(result,HCBREAD,pHcb);
|
AppendHipadabaCallback(result,HCBREAD,pHcb);
|
||||||
@ -626,7 +667,7 @@ pHdb MakeSICSROPar(char *name, hdbValue v){
|
|||||||
|
|
||||||
pHcb = MakeReadOnlyCallback();
|
pHcb = MakeReadOnlyCallback();
|
||||||
if(pHcb == NULL){
|
if(pHcb == NULL){
|
||||||
DeleteHipadabaNode(result);
|
DeleteHipadabaNode(result,NULL);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
AppendHipadabaCallback(result,HCBSET,pHcb);
|
AppendHipadabaCallback(result,HCBSET,pHcb);
|
||||||
@ -647,21 +688,21 @@ pHdb MakeSICSScriptPar(char *name, char *setScript, char *readScript,
|
|||||||
|
|
||||||
pHcb = MakeSICSWriteScriptCallback(setScript);
|
pHcb = MakeSICSWriteScriptCallback(setScript);
|
||||||
if(pHcb == NULL){
|
if(pHcb == NULL){
|
||||||
DeleteHipadabaNode(result);
|
DeleteHipadabaNode(result,NULL);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
AppendHipadabaCallback(result,HCBSET,pHcb);
|
AppendHipadabaCallback(result,HCBSET,pHcb);
|
||||||
|
|
||||||
pHcb = MakeSICSReadScriptCallback(readScript);
|
pHcb = MakeSICSReadScriptCallback(readScript);
|
||||||
if(pHcb == NULL){
|
if(pHcb == NULL){
|
||||||
DeleteHipadabaNode(result);
|
DeleteHipadabaNode(result,NULL);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
AppendHipadabaCallback(result,HCBREAD,pHcb);
|
AppendHipadabaCallback(result,HCBREAD,pHcb);
|
||||||
/**
|
/**
|
||||||
* put into the list of nodes to check with the update task
|
* put into the list of nodes to check with the update task
|
||||||
*/
|
*/
|
||||||
LLDnodeAppend(scriptUpdate,&result);
|
/* LLDnodeAppend(scriptUpdate,&result); */
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -675,15 +716,12 @@ pHdb CreateSICSScriptPar(char *name, char *setScript, char *readScript,
|
|||||||
static void removeNodeFromUpdateList(pHdb node){
|
static void removeNodeFromUpdateList(pHdb node){
|
||||||
pHdb current = NULL;
|
pHdb current = NULL;
|
||||||
int status;
|
int status;
|
||||||
|
char *objName = NULL;
|
||||||
|
|
||||||
status = LLDnodePtr2First(scriptUpdate);
|
objName = GetHipadabaPath(node);
|
||||||
while(status != 0){
|
if(objName != NULL){
|
||||||
current = LLDnodePtr(scriptUpdate);
|
removePollObject(poller, objName);
|
||||||
if(current == node){
|
free(objName);
|
||||||
LLDnodeDelete(scriptUpdate);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
status = LLDnodePtr2Next(scriptUpdate);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
@ -693,6 +731,13 @@ static void SICSDeleteNodeData(pHdb node){
|
|||||||
if(node == NULL){
|
if(node == NULL){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeNodeFromUpdateList(node);
|
||||||
|
while(node->child != NULL){
|
||||||
|
tmp = node->child;
|
||||||
|
node->child = node->child->next;
|
||||||
|
SICSDeleteNodeData(tmp);
|
||||||
|
}
|
||||||
DeleteCallbackChain(node->writeCallbacks);
|
DeleteCallbackChain(node->writeCallbacks);
|
||||||
DeleteCallbackChain(node->updateCallbacks);
|
DeleteCallbackChain(node->updateCallbacks);
|
||||||
DeleteCallbackChain(node->readCallbacks);
|
DeleteCallbackChain(node->readCallbacks);
|
||||||
@ -703,23 +748,17 @@ static void SICSDeleteNodeData(pHdb node){
|
|||||||
ReleaseHdbValue(&node->value);
|
ReleaseHdbValue(&node->value);
|
||||||
node->magic = 000000;
|
node->magic = 000000;
|
||||||
|
|
||||||
while(node->child != NULL){
|
|
||||||
tmp = node->child;
|
|
||||||
node->child = node->child->next;
|
|
||||||
SICSDeleteNodeData(tmp);
|
|
||||||
}
|
|
||||||
removeNodeFromUpdateList(node);
|
|
||||||
free(node);
|
free(node);
|
||||||
}
|
}
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
void RemoveSICSPar(pHdb node){
|
void RemoveSICSPar(pHdb node, void *callData){
|
||||||
pHdb current = NULL, tmp = NULL;
|
pHdb current = NULL, tmp = NULL;
|
||||||
|
|
||||||
if(node == NULL){
|
if(node == NULL){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveHdbNodeFromParent(node);
|
RemoveHdbNodeFromParent(node,NULL);
|
||||||
|
|
||||||
SICSDeleteNodeData(node);
|
SICSDeleteNodeData(node);
|
||||||
}
|
}
|
||||||
@ -731,7 +770,7 @@ int AddSICSHdbPar(pHdb node, char *name, int priv, hdbValue v){
|
|||||||
if(child == NULL){
|
if(child == NULL){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
AddHipadabaChild(node,child);
|
AddHipadabaChild(node,child,NULL);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
@ -742,7 +781,7 @@ int AddSICSHdbROPar(pHdb node, char *name, hdbValue v){
|
|||||||
if(child == NULL){
|
if(child == NULL){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
AddHipadabaChild(node,child);
|
AddHipadabaChild(node,child,NULL);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
@ -763,25 +802,25 @@ int AddSICSHdbMemPar(pHdb node, char *name, int priv,
|
|||||||
|
|
||||||
pHcb = MakeCheckPermissionCallback(priv);
|
pHcb = MakeCheckPermissionCallback(priv);
|
||||||
if(pHcb == NULL){
|
if(pHcb == NULL){
|
||||||
DeleteHipadabaNode(child);
|
DeleteHipadabaNode(child,NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
AppendHipadabaCallback(child,HCBSET,pHcb);
|
AppendHipadabaCallback(child,HCBSET,pHcb);
|
||||||
|
|
||||||
pHcb = MakeMemGenSetCallback(data);
|
pHcb = MakeMemGenSetCallback(data);
|
||||||
if(pHcb == NULL){
|
if(pHcb == NULL){
|
||||||
DeleteHipadabaNode(child);
|
DeleteHipadabaNode(child,NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
AppendHipadabaCallback(child,HCBSET,pHcb);
|
AppendHipadabaCallback(child,HCBSET,pHcb);
|
||||||
|
|
||||||
pHcb = MakeMemGenReadCallback(data);
|
pHcb = MakeMemGenReadCallback(data);
|
||||||
if(pHcb == NULL){
|
if(pHcb == NULL){
|
||||||
DeleteHipadabaNode(child);
|
DeleteHipadabaNode(child,NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
AppendHipadabaCallback(child,HCBREAD,pHcb);
|
AppendHipadabaCallback(child,HCBREAD,pHcb);
|
||||||
AddHipadabaChild(node,child);
|
AddHipadabaChild(node,child,NULL);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -887,13 +926,16 @@ int SICSHdbSetPar(void *obj, SConnection *pCon,
|
|||||||
int InstallSICSNotify(pHdb node, SConnection *pCon, int id, int recurse){
|
int InstallSICSNotify(pHdb node, SConnection *pCon, int id, int recurse){
|
||||||
pHdb currentChild = NULL;
|
pHdb currentChild = NULL;
|
||||||
pHdbCallback noty = NULL;
|
pHdbCallback noty = NULL;
|
||||||
|
pHdbCallback treeChange = NULL;
|
||||||
|
|
||||||
|
treeChange = MakeTreeChangeCallback(pCon,id);
|
||||||
noty = MakeNotifyCallback(pCon,id);
|
noty = MakeNotifyCallback(pCon,id);
|
||||||
if(noty == NULL){
|
if(noty == NULL || treeChange == NULL){
|
||||||
SCWrite(pCon,"ERROR: out of memory installing callback", eError);
|
SCWrite(pCon,"ERROR: out of memory installing callback", eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
AppendHipadabaCallback(node, HCBUPDATE, noty);
|
AppendHipadabaCallback(node, HCBUPDATE, noty);
|
||||||
|
AppendHipadabaCallback(node, HCBTREE, treeChange);
|
||||||
|
|
||||||
if(recurse == 1){
|
if(recurse == 1){
|
||||||
currentChild = node->child;
|
currentChild = node->child;
|
||||||
@ -1041,60 +1083,6 @@ void SaveSICSHipadaba(FILE *fd, pHdb node, char *prefix){
|
|||||||
currentChild = currentChild->next;
|
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 ============================================*/
|
/*================ value helpers ============================================*/
|
||||||
pDynString formatValue(hdbValue v){
|
pDynString formatValue(hdbValue v){
|
||||||
pDynString result = NULL;
|
pDynString result = NULL;
|
||||||
@ -1162,8 +1150,10 @@ static char *getNextHdbNumber(char *pStart, char pNumber[80]){
|
|||||||
static int adjustDataLength(hdbValue *v, char *data){
|
static int adjustDataLength(hdbValue *v, char *data){
|
||||||
char number[80];
|
char number[80];
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
char *pPtr = NULL;
|
||||||
|
|
||||||
while(getNextHdbNumber(data,number) != NULL){
|
pPtr = data;
|
||||||
|
while((pPtr = getNextHdbNumber(pPtr,number)) != NULL){
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
if(count != v->arrayLength){
|
if(count != v->arrayLength){
|
||||||
@ -1315,6 +1305,7 @@ static int MakeHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
char *pPtr = NULL;
|
char *pPtr = NULL;
|
||||||
pHdb parent = NULL;
|
pHdb parent = NULL;
|
||||||
pHdb child = NULL;
|
pHdb child = NULL;
|
||||||
|
char buffer[512], buffer2[512];
|
||||||
|
|
||||||
if(!SCMatchRights(pCon,usMugger)){
|
if(!SCMatchRights(pCon,usMugger)){
|
||||||
return 0;
|
return 0;
|
||||||
@ -1351,7 +1342,8 @@ static int MakeHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* split off last path element */
|
/* split off last path element */
|
||||||
pPtr = strrchr(argv[1],'/');
|
strncpy(buffer,argv[1],511);
|
||||||
|
pPtr = strrchr(buffer,'/');
|
||||||
if(pPtr == NULL){
|
if(pPtr == NULL){
|
||||||
SCWrite(pCon,"ERROR: invalid path specification",
|
SCWrite(pCon,"ERROR: invalid path specification",
|
||||||
eError);
|
eError);
|
||||||
@ -1362,10 +1354,12 @@ static int MakeHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
if(strlen(pPtr) < 1) {
|
if(strlen(pPtr) < 1) {
|
||||||
parent = root;
|
parent = root;
|
||||||
} else {
|
} else {
|
||||||
parent = GetHipadabaNode(root,argv[1]);
|
parent = GetHipadabaNode(root,buffer);
|
||||||
}
|
}
|
||||||
if(parent == NULL){
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
if(type != HIPNONE){
|
if(type != HIPNONE){
|
||||||
@ -1378,7 +1372,7 @@ static int MakeHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddHipadabaChild(parent,child);
|
AddHipadabaChild(parent,child,pCon);
|
||||||
SCSendOK(pCon);
|
SCSendOK(pCon);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1390,6 +1384,10 @@ static int MakeHdbScriptNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
pHdb parent = NULL;
|
pHdb parent = NULL;
|
||||||
pHdb child = NULL;
|
pHdb child = NULL;
|
||||||
pHdb current = NULL;
|
pHdb current = NULL;
|
||||||
|
char *urgv[] = {"5", NULL};
|
||||||
|
char driver[] = {"hdb"};
|
||||||
|
char buffer[512], buffer2[512];
|
||||||
|
|
||||||
|
|
||||||
if(!SCMatchRights(pCon,usMugger)){
|
if(!SCMatchRights(pCon,usMugger)){
|
||||||
return 0;
|
return 0;
|
||||||
@ -1422,7 +1420,8 @@ static int MakeHdbScriptNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* split off last path element */
|
/* split off last path element */
|
||||||
pPtr = strrchr(argv[1],'/');
|
strncpy(buffer,argv[1],511);
|
||||||
|
pPtr = strrchr(buffer,'/');
|
||||||
if(pPtr == NULL){
|
if(pPtr == NULL){
|
||||||
SCWrite(pCon,"ERROR: invalid path specification",
|
SCWrite(pCon,"ERROR: invalid path specification",
|
||||||
eError);
|
eError);
|
||||||
@ -1433,10 +1432,12 @@ static int MakeHdbScriptNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
if(strlen(pPtr) < 1) {
|
if(strlen(pPtr) < 1) {
|
||||||
parent = root;
|
parent = root;
|
||||||
} else {
|
} else {
|
||||||
parent = GetHipadabaNode(root,argv[1]);
|
parent = GetHipadabaNode(root,buffer);
|
||||||
}
|
}
|
||||||
if(parent == NULL){
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
child = MakeSICSScriptPar(pPtr, argv[3], argv[2],
|
child = MakeSICSScriptPar(pPtr, argv[3], argv[2],
|
||||||
@ -1446,11 +1447,32 @@ static int MakeHdbScriptNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddHipadabaChild(parent,child);
|
AddHipadabaChild(parent,child,pCon);
|
||||||
|
/*
|
||||||
|
* have it polled automatically
|
||||||
|
*/
|
||||||
|
addPollObject(poller,pCon, GetHipadabaPath(child),driver,1,urgv);
|
||||||
|
|
||||||
SCSendOK(pCon);
|
SCSendOK(pCon);
|
||||||
return 1;
|
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,
|
static int DeleteHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[]){
|
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);
|
SCWrite(pCon,"ERROR: node to delete not found",eError);
|
||||||
return 0;
|
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);
|
SCSendOK(pCon);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1927,7 +1955,7 @@ static int LinkHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddHipadabaChild(node,pDum->pDescriptor->parNode);
|
AddHipadabaChild(node,pDum->pDescriptor->parNode,pCon);
|
||||||
|
|
||||||
if(argc > 3){
|
if(argc > 3){
|
||||||
if(pDum->pDescriptor->parNode->name != NULL){
|
if(pDum->pDescriptor->parNode->name != NULL){
|
||||||
@ -1939,41 +1967,75 @@ static int LinkHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
SCSendOK(pCon);
|
SCSendOK(pCon);
|
||||||
return 1;
|
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(){
|
void killSICSHipadaba(){
|
||||||
if(root != NULL){
|
if(root != NULL){
|
||||||
DeleteHipadabaNode(root);
|
DeleteHipadabaNode(root,NULL);
|
||||||
}
|
}
|
||||||
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 InstallSICSHipadaba(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[]){
|
int argc, char *argv[]){
|
||||||
|
|
||||||
root = MakeHipadabaNode("/",HIPNONE,0);
|
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,"hmake", MakeHdbNode, NULL, NULL);
|
||||||
AddCommand(pSics,"hmakescript", MakeHdbScriptNode, NULL, NULL);
|
AddCommand(pSics,"hmakescript", MakeHdbScriptNode, NULL, NULL);
|
||||||
|
AddCommand(pSics,"hattach", SICSHdbAdapter, NULL, NULL);
|
||||||
AddCommand(pSics,"hdel", DeleteHdbNode, NULL, NULL);
|
AddCommand(pSics,"hdel", DeleteHdbNode, NULL, NULL);
|
||||||
AddCommand(pSics,"hset", SetHdbNode, NULL, NULL);
|
AddCommand(pSics,"hset", SetHdbNode, NULL, NULL);
|
||||||
AddCommand(pSics,"hget", GetHdbNode, 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,"hlink", LinkHdbNode, NULL, NULL);
|
||||||
AddCommand(pSics,"hinfo", HdbNodeInfo, NULL, NULL);
|
AddCommand(pSics,"hinfo", HdbNodeInfo, NULL, NULL);
|
||||||
AddCommand(pSics,"hval", HdbNodeVal, 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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,11 @@ typedef struct {
|
|||||||
int iEnd;
|
int iEnd;
|
||||||
}hdbUpdateTask, *pHdbUpdateTask;
|
}hdbUpdateTask, *pHdbUpdateTask;
|
||||||
/*======================== common callbacks =====================================*/
|
/*======================== 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
|
* make a callback which checks permissions. To be used on write
|
||||||
* @param priv The privilege to check against
|
* @param priv The privilege to check against
|
||||||
@ -107,6 +112,13 @@ pHdbCallback MakeMemReadCallback(float *address);
|
|||||||
* @return a suitable callback for setting this parameter.
|
* @return a suitable callback for setting this parameter.
|
||||||
*/
|
*/
|
||||||
pHdbCallback MakeMemSetCallback(float *address);
|
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 ===================================*/
|
/*======================== parameter creation ===================================*/
|
||||||
/**
|
/**
|
||||||
* make a simple SICS hdb parameter. Setting it will call update immediately. Use
|
* make a simple SICS hdb parameter. Setting it will call update immediately. Use
|
||||||
@ -184,8 +196,9 @@ pHdb CreateSICSScriptPar(char *name, char *setScript, char *readScript,
|
|||||||
* normal DeletHipadabaNode, this function also takes care of
|
* normal DeletHipadabaNode, this function also takes care of
|
||||||
* clearing scipted nodes out of the update tasks watch list.
|
* clearing scipted nodes out of the update tasks watch list.
|
||||||
* @param node The node to delete
|
* @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 par functions =======================================*/
|
||||||
/**
|
/**
|
||||||
* add a new simple hdb parameter as child to node
|
* 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) {
|
char *Arg2Tcl(int argc, char *argv[], char *buffer, int buffersize) {
|
||||||
return Arg2Tcl0(argc, argv, buffer, buffersize, NULL);
|
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
|
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.
|
If prepend is not NULL, its contents appear untreated before the args.
|
||||||
A space is used as separator.
|
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
|
#endif
|
||||||
|
8
tasub.c
8
tasub.c
@ -1610,9 +1610,13 @@ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
|
|||||||
|
|
||||||
strtolower(argv[1]);
|
strtolower(argv[1]);
|
||||||
if(strcmp(argv[1],"mono") == 0){
|
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){
|
} 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){
|
}else if(strcmp(argv[1],"cell") == 0){
|
||||||
if(argc > 2){
|
if(argc > 2){
|
||||||
return tasReadCell(pCon,self,argc,argv);
|
return tasReadCell(pCon,self,argc,argv);
|
||||||
|
Reference in New Issue
Block a user