- allow scriptcontext objects to be dynamic
- enhancements in scriptcontext (error messages stored as properties)
This commit is contained in:
136
sctdriveobj.c
136
sctdriveobj.c
@ -3,6 +3,19 @@
|
||||
* scriptcontext to control the actual driving operation. This can also
|
||||
* serve as a drivable adapter to nodes in other objects.
|
||||
*
|
||||
* 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:
|
||||
*
|
||||
* checklimits, for limits checking
|
||||
* checkstatus, for evaluating progress
|
||||
* halt , for halting things
|
||||
*
|
||||
* If no checklimits script is given, nothing is checked.
|
||||
* If no checkstatus scripts is given, the value of the status property is
|
||||
* returned. In that case the status value should be updated by some poll script.
|
||||
* If no halt script is given, the status is set to idle. M.Z. Sept. 08
|
||||
*
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, June-July 2008
|
||||
@ -22,18 +35,19 @@ typedef struct {
|
||||
/*--------------------------------------------------------------*/
|
||||
static void KillDrivePriv(void *data)
|
||||
{
|
||||
pDrivObjPriv priv = (pDrivObjPriv)data;
|
||||
if(priv == NULL){
|
||||
pDrivObjPriv priv = (pDrivObjPriv) data;
|
||||
if (priv == NULL) {
|
||||
return;
|
||||
}
|
||||
if(priv->pDriv != NULL){
|
||||
if (priv->pDriv != NULL) {
|
||||
free(priv->pDriv);
|
||||
}
|
||||
if(priv->pCon != NULL){
|
||||
if (priv->pCon != NULL) {
|
||||
SCDeleteConnection(priv->pCon);
|
||||
}
|
||||
free(priv);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------*/
|
||||
static void *SCTDRIVGetInterface(void *data, int iD)
|
||||
{
|
||||
@ -65,8 +79,8 @@ static int SCTDRIVHalt(void *data)
|
||||
self = (pSICSOBJ) data;
|
||||
pPriv = (pDrivObjPriv) self->pPrivate;
|
||||
if (GetHdbProperty(self->objectNode, "halt", dummy, sizeof dummy)) {
|
||||
SctQueueNode(pPriv->c, self->objectNode, HaltPRIO, "halt",
|
||||
pPriv->pCon);
|
||||
SctQueueNode(pPriv->c, self->objectNode, HaltPRIO, "halt",
|
||||
pPriv->pCon);
|
||||
} else
|
||||
if (GetHdbProperty(self->objectNode, "status", dummy, sizeof dummy))
|
||||
{
|
||||
@ -128,11 +142,13 @@ static long SCTDRIVSetValue(void *data, SConnection * pCon, float val)
|
||||
|
||||
self = (pSICSOBJ) data;
|
||||
pPriv = (pDrivObjPriv) self->pPrivate;
|
||||
if(pPriv->pCon != NULL){
|
||||
if (pPriv->pCon != NULL) {
|
||||
SCDeleteConnection(pPriv->pCon);
|
||||
}
|
||||
pPriv->pCon = SCCopyConnection(pCon);
|
||||
|
||||
StopByData(pServ->pExecutor, data);
|
||||
|
||||
v.dataType = HIPFLOAT;
|
||||
v.v.doubleValue = (double) val;
|
||||
SetHdbProperty(self->objectNode, "writestatus", "start");
|
||||
@ -258,24 +274,17 @@ static void KillDriveOBJ(void *data)
|
||||
}
|
||||
|
||||
pPriv = (pDrivObjPriv) self->pPrivate;
|
||||
if (pPriv->doNotKillNode && self->pDes != NULL) {
|
||||
if (self->pDes->name)
|
||||
free(self->pDes->name);
|
||||
if (self->pDes->pKeys)
|
||||
IFDeleteOptions(self->pDes->pKeys);
|
||||
free(self->pDes);
|
||||
} else {
|
||||
DeleteDescriptor(self->pDes); /* kill descriptor including node */
|
||||
if (pPriv->doNotKillNode && GetDescriptorKey(self->pDes, "creationCommand") == NULL /* it's not a dynamic object */
|
||||
&& self->pDes != NULL) {
|
||||
self->objectNode = NULL; /* do not call RemoveHdbNodeFromParent in KillSICSOBJ */
|
||||
self->pDes->parNode = NULL; /* do not kill the node in KillSICSOBJ/DeleteDescriptor */
|
||||
}
|
||||
if (self->KillPrivate != NULL && self->pPrivate != NULL) {
|
||||
self->KillPrivate(self->pPrivate);
|
||||
}
|
||||
RemoveHdbNodeFromParent(self->objectNode, pServ->dummyCon);
|
||||
free(self);
|
||||
KillSICSOBJ(self);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
pSICSOBJ MakeSctDriveObj(pHdb node, char *class, SctController * c)
|
||||
pSICSOBJ MakeSctDriveObj(pHdb node, char *class, SctController * c,
|
||||
int doNotKillNode)
|
||||
{
|
||||
pSICSOBJ pNew = NULL;
|
||||
pDrivObjPriv pPriv = NULL;
|
||||
@ -299,6 +308,7 @@ pSICSOBJ MakeSctDriveObj(pHdb node, char *class, SctController * c)
|
||||
pNew->objectNode = node;
|
||||
AssignSctDrive(pPriv->pDriv);
|
||||
pPriv->c = c;
|
||||
pPriv->doNotKillNode = doNotKillNode;
|
||||
pNew->pDes->parNode = pNew->objectNode;
|
||||
pNew->pDes->GetInterface = SCTDRIVGetInterface;
|
||||
pNew->pPrivate = pPriv;
|
||||
@ -309,7 +319,7 @@ pSICSOBJ MakeSctDriveObj(pHdb node, char *class, SctController * c)
|
||||
/*--------------------------------------------------------------------------
|
||||
* This actually has two syntaxes:
|
||||
* makesctdrive name path-to-existing-node class SctController
|
||||
* makesctdrive name type priv class SctController
|
||||
* makesctdrive name float priv class SctController
|
||||
*--------------------------------------------------------------------------*/
|
||||
int SctMakeDriveObject(SConnection * pCon, SicsInterp * pSics,
|
||||
void *object, int argc, char *argv[])
|
||||
@ -319,54 +329,58 @@ int SctMakeDriveObject(SConnection * pCon, SicsInterp * pSics,
|
||||
pSICSOBJ pNew = NULL;
|
||||
pSICSOBJ pSct = NULL;
|
||||
SctController *c = NULL;
|
||||
int priv, type, status;
|
||||
int priv, type, status, doNotKillNode;
|
||||
hdbValue val;
|
||||
char *sctName;
|
||||
char *class;
|
||||
|
||||
if (argc < 5) {
|
||||
SCWrite(pCon, "ERROR: not enough arguments to SctMakeDriveObject",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
if (argc < 5)
|
||||
goto Usage;
|
||||
|
||||
node = FindHdbNode(NULL, argv[2], pCon);
|
||||
if (node != NULL) {
|
||||
pSct = FindCommandData(pSics, argv[4], "SctController");
|
||||
if (pSct == NULL) {
|
||||
SCPrintf(pCon, eError, "ERROR: SctController %s not found", argv[4]);
|
||||
return 0;
|
||||
if (argc == 5) {
|
||||
node = FindHdbNode(NULL, argv[2], pCon);
|
||||
if (node == NULL) {
|
||||
SCPrintf(pCon, eError, "ERROR: node %s not found", argv[2]);
|
||||
goto Usage;
|
||||
}
|
||||
c = (SctController *) pSct->pPrivate;
|
||||
pNew = MakeSctDriveObj(node, argv[3], c);
|
||||
pPriv = (pDrivObjPriv) pNew->pPrivate;
|
||||
pPriv->doNotKillNode = 1; /* the node is owned by someone else */
|
||||
sctName = argv[4];
|
||||
class = argv[3];
|
||||
doNotKillNode = 1; /* the node is owned by someone else */
|
||||
} else {
|
||||
/* convert datatype */
|
||||
type = convertHdbType(argv[2]);
|
||||
/* convert privilege */
|
||||
priv = decodeSICSPriv(argv[3]);
|
||||
/* convert datatype */
|
||||
strtolower(argv[4]);
|
||||
type = convertHdbType(argv[2]);
|
||||
if (type == HIPNONE) {
|
||||
node = MakeHipadabaNode(argv[1], HIPNONE, 1);
|
||||
} else {
|
||||
val = makeHdbValue(type, 0);
|
||||
node = MakeSICSHdbPar(argv[1], priv, val);
|
||||
ReleaseHdbValue(&val);
|
||||
}
|
||||
if (priv < 0 || type != HIPFLOAT)
|
||||
goto Usage;
|
||||
node = MakeSICSHdbPar(argv[1], priv, MakeHdbFloat(0.0));
|
||||
if (node == NULL) {
|
||||
SCWrite(pCon, "ERROR: node creation failed", eError);
|
||||
return 0;
|
||||
}
|
||||
c = FindCommandData(pSics, argv[5], "SctController");
|
||||
if (c == NULL) {
|
||||
SCPrintf(pCon, eError, "ERROR: SctController %s not found", argv[4]);
|
||||
return 0;
|
||||
}
|
||||
pNew = MakeSctDriveObj(node, argv[3], c);
|
||||
sctName = argv[5];
|
||||
class = argv[4];
|
||||
doNotKillNode = 0; /* kill the node with the command */
|
||||
}
|
||||
|
||||
pSct = FindCommandData(pSics, sctName, "SctController");
|
||||
if (pSct == NULL) {
|
||||
SCPrintf(pCon, eError, "ERROR: SctController %s not found", sctName);
|
||||
goto Usage;
|
||||
}
|
||||
c = (SctController *) pSct->pPrivate;
|
||||
pNew = MakeSctDriveObj(node, class, c, doNotKillNode);
|
||||
SetHdbProperty(node, "objectName", argv[1]);
|
||||
|
||||
if (pNew == NULL) {
|
||||
SCWrite(pCon, "ERROR: failed to create drive object", eError);
|
||||
return 0;
|
||||
}
|
||||
if (strcasecmp(argv[0], "dynsctdriveobj") == 0) {
|
||||
/* make object dynamic by defining a creation command */
|
||||
SetDescriptorKey(pNew->pDes, "creationCommand", "0");
|
||||
RegisterSICSOBJKillCmd(pNew, argv[1]);
|
||||
}
|
||||
status = AddCommand(pSics,
|
||||
argv[1], InterInvokeSICSOBJ, KillDriveOBJ, pNew);
|
||||
if (status != 1) {
|
||||
@ -376,4 +390,18 @@ int SctMakeDriveObject(SConnection * pCon, SicsInterp * pSics,
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
Usage:
|
||||
SCPrintf(pCon, eError,
|
||||
"ERROR: should be %s <object name> <existing node> <class> <controller>",
|
||||
argv[0]);
|
||||
SCPrintf(pCon, eError,
|
||||
"ERROR: or %s <object name> <type> <priv> <class> <controller>",
|
||||
argv[0]);
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------*/
|
||||
void SctDriveObjInit(void)
|
||||
{
|
||||
AddCmd("makesctdriveobj", SctMakeDriveObject);
|
||||
AddCmd("dynsctdriveobj", SctMakeDriveObject);
|
||||
}
|
||||
|
Reference in New Issue
Block a user