- added scriptcontext.h

- killing a node using sct should now be safe
- sctdrive adapter object might be dynamic
- default for the checkstatus script: returning the status property
- introduced <sctcon> unpoll
- changed <sctcon> queuecon to <sctcon> send
- some more improvements in sct
This commit is contained in:
zolliker
2008-06-13 11:22:13 +00:00
parent d75eee789b
commit 9e7a6cfd74
7 changed files with 366 additions and 150 deletions

View File

@ -3,7 +3,7 @@
* scriptcontext generic device model. This is a wrapper around
* such a node which implements the drivable interface.
*
* Soem cooperation from the node is required: It has to provide
* Some cooperation from the node is required: It has to provide
* certain properties the value of which define scripts which
* have to be called at various stages. These are:
*
@ -21,13 +21,7 @@
#include <tcl.h>
#include <macro.h>
#include <sicsobj.h>
/*------------- Some things from scriptcontext.c ----------------*/
typedef struct SctController SctController;
typedef struct SctData SctData;
SctData *SctQueueNode(SctController *controller, pHdb node,
DevPrio prio, char *action);
int SctCallInContext(SConnection *con, char *script, Hdb *node,
SctController *controller, char **resPtr);
#include "scriptcontext.h"
/*---------------------------------------------------------------*/
typedef struct {
pObjectDescriptor pDes;
@ -41,6 +35,7 @@ static void *SCTDRIVGetInterface(void *data, int iD){
self = (pSctDrive)data;
if(self != NULL && iD == DRIVEID){
if (self->node == NULL) return NULL;
return self->pDriv;
} else {
return NULL;
@ -53,14 +48,14 @@ static void *SCTDRIVGetInterface(void *data, int iD){
------------------------------------------------------------------*/
static int SCTDRIVHalt(void *data) {
pSctDrive self = NULL;
char dummy[16];
self = (pSctDrive)data;
SctQueueNode(self->c, self->node, HaltPRIO, "halt");
/*
* SctQueueNode returns a dynamically allocated SctData
* structure. I am not sure if this is not really a memory
* leak
*/
if (GetHdbProperty(self->node,"halt", dummy, sizeof dummy)) {
SctQueueNode(self->c, self->node, HaltPRIO, "halt", NULL);
} else if (GetHdbProperty(self->node, "status", dummy, sizeof dummy)) {
SetHdbProperty(self->node, "status", "idle");
}
return OKOK;
}
/*----------------------------------------------------------------
@ -85,6 +80,7 @@ static int SCTDRIVCheckLimits(void *data, float val,
self->node, self->c, &result);
if(status == 0){
strncpy(error,result,errlen);
return 0;
}
}
return 1;
@ -132,31 +128,34 @@ static int SCTDRIVCheckStatus(void *data, SConnection *pCon){
self = (pSctDrive)data;
if(GetHdbProperty(self->node,"checkstatus",script,1024)){
status = SctCallInContext(pCon,script, self->node,
self->c, &result);
if(status == 1){
if(strstr(result,"busy") != NULL){
return HWBusy;
} else if(strstr(result,"posfault") != NULL){
return HWPosFault;
} else if(strstr(result,"fault") != NULL){
return HWFault;
} else if(strstr(result,"idle") != NULL){
return HWIdle;
} else {
SCPrintf(pCon,eError,"ERROR: invalid status code %s returned from checkstatus script",
result);
return HWFault;
}
} else {
SCWrite(pCon,result, eError);
return HWFault;
}
if(!GetHdbProperty(self->node,"checkstatus",script,1024)){
if (!GetHdbProperty(self->node,"status",script,1024)){
SCWrite(pCon,
"ERROR: configuration problem: no checkstatus script!", eError);
return HWFault;
}
result = script;
} else {
SCWrite(pCon,
"ERROR: configuration problem: no checkstatus script!", eError);
return HWFault;
status = SctCallInContext(pCon,script, self->node,
self->c, &result);
if (status == 0) {
SCWrite(pCon,result, eError);
return HWFault;
}
}
if(strstr(result,"busy") != NULL){
return HWBusy;
} else if(strstr(result,"posfault") != NULL){
return HWPosFault;
} else if(strstr(result,"fault") != NULL){
return HWFault;
} else if(strstr(result,"idle") != NULL){
return HWIdle;
} else {
SCPrintf(pCon,eError,
"ERROR: invalid status code %s returned from checkstatus script",
result);
return HWFault;
}
return HWFault;
}
@ -212,6 +211,10 @@ static int SctDriveCommand(SConnection *pCon, SicsInterp *sics, void *object,
assert(self != NULL);
if (self->node == NULL) {
SCWrite(pCon, "ERROR: defunct object", eError);
return 0;
}
/*
* only action: print value
*/
@ -234,15 +237,26 @@ static void SctDriveKill(void *data){
}
free(self);
}
/*----------------------------------------------------------------*/
static hdbCallbackReturn SctDummyCallback(Hdb *node, void *userData,
hdbMessage *msg) {
return hdbContinue;
}
/*----------------------------------------------------------------*/
static void SctDriveDeleteNode(void *data) {
pSctDrive self = (pSctDrive)data;
self->node = NULL;
}
/*---------------------------------------------------------------*/
int SctMakeDriveAdapter(SConnection *pCon, SicsInterp *pSics, void *object,
int argc, char *argv[]) {
pSctDrive pNew = NULL;
pSICSOBJ obj = NULL;
hdbCallback *cb;
pNew = SCTDRIVMakeObject();
if(pNew == NULL){
SCWrite(pCon,"ERROR: out of memory in SctmakeDriveAdapter",
SCWrite(pCon,"ERROR: out of memory in SctMakeDriveAdapter",
eError);
return 0;
}
@ -260,7 +274,22 @@ int SctMakeDriveAdapter(SConnection *pCon, SicsInterp *pSics, void *object,
return 0;
}
pNew->c =(SctController *)obj->pPrivate;
if (strcasecmp(argv[0],"dynsctdrive") == 0) {
/* make object dynamic by defining a descriptor command */
SetDescriptorKey(pNew->pDes, "creationCommand", "0");
}
AddCommand(pSics, argv[1], SctDriveCommand, SctDriveKill, pNew);
SetHdbProperty(pNew->node,"sicsdev",argv[1]);
cb = MakeHipadabaCallback(SctDummyCallback, pNew, SctDriveDeleteNode);
assert(cb);
AppendHipadabaCallback(pNew->node, cb);
return 1;
}
/*---------------------------------------------------------------*/
void SctDriveInit(void) {
AddCmd("makesctdrive", SctMakeDriveAdapter);
AddCmd("dynsctdrive", SctMakeDriveAdapter);
}