724 lines
20 KiB
C
724 lines
20 KiB
C
/*-----------------------------------------------------------------------
|
|
A configurable virtual motor object. At motor start a script is called
|
|
which returns the motors and positions to drive as a comma separated
|
|
list holding entries of the form mot=value.
|
|
|
|
This is the implementation file.
|
|
|
|
COPYRIGHT: see file COPYRIGHT
|
|
|
|
Mark Koennecke, August 2004
|
|
interest added: Ferdi Franceschini, April 2006
|
|
|
|
Additions:
|
|
- a checkscript to be run at the end of driving the motor
|
|
- a means to call the write script multiple times. This is useful if
|
|
you need to drive to the value in multiple steps. An example is the
|
|
BOA double crystal monochromator where you first have to put the blades to
|
|
0, then drive the translation and then drive the blades to the real theta.
|
|
All this to avoid collisions. In order to support this, a state field and
|
|
and a readable target field has been added. The mode of operation is such
|
|
that the on first run the, writescript set the state to something different
|
|
then idle. This causes after the first set of motors finished running the
|
|
writescript to be called again. This can figure out by lookin at the
|
|
state variable what to do. This can be done in repetition until the
|
|
writescript sets state to idle again.
|
|
|
|
Mark Koennecke, April 2012
|
|
-------------------------------------------------------------------------*/
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include "fortify.h"
|
|
#include <tcl.h>
|
|
#include "lld.h"
|
|
#include "splitter.h"
|
|
#include "confvirtmot.h"
|
|
#include "confvirtmot.i"
|
|
|
|
#define BAD_VALUE (-9999.99)
|
|
|
|
extern char *stptok(char *s, char *t, int len, char *brk);
|
|
extern int CheckMotiMatch(const void* context, const void* pUserData);
|
|
extern double DoubleTime(void);
|
|
|
|
/*---------------------------------------------------------------------------
|
|
An internal data structure which holds information required to control
|
|
the real motors
|
|
----------------------------------------------------------------------------*/
|
|
typedef struct {
|
|
char name[132];
|
|
void *data;
|
|
pIDrivable pDriv;
|
|
float value;
|
|
int running;
|
|
long taskID;
|
|
} RealMotor, *pRealMotor;
|
|
|
|
/* Data passed by event generating object */
|
|
typedef struct {
|
|
float fVal;
|
|
char *pName;
|
|
} EventInfo;
|
|
|
|
/* Data available when registering interest */
|
|
typedef struct {
|
|
char *pName;
|
|
SConnection *pCon;
|
|
float lastValue;
|
|
} RegisteredInfo, *pRegisteredInfo;
|
|
|
|
/*---------------------------------------------------------------------*/
|
|
static int HaltMotors(void *pData)
|
|
{
|
|
pConfigurableVirtualMotor self = (pConfigurableVirtualMotor) pData;
|
|
RealMotor tuktuk;
|
|
int iRet;
|
|
|
|
iRet = LLDnodePtr2First(self->motorList);
|
|
while (iRet != 0) {
|
|
LLDnodeDataTo(self->motorList, &tuktuk);
|
|
tuktuk.pDriv->Halt(tuktuk.data);
|
|
iRet = LLDnodePtr2Next(self->motorList);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
static char *invokeMotorScript(pConfigurableVirtualMotor self,
|
|
float newValue)
|
|
{
|
|
char pBueffel[512];
|
|
Tcl_Interp *pTcl;
|
|
int status;
|
|
|
|
self->parseOK = 1;
|
|
if (self->scriptName == NULL) {
|
|
snprintf(self->scriptError, 511,
|
|
"ERROR: no script configured for configurable virtual motor");
|
|
self->parseOK = 0;
|
|
return NULL;
|
|
}
|
|
|
|
snprintf(pBueffel, 510, "%s %f", self->scriptName, newValue);
|
|
pTcl = InterpGetTcl(pServ->pSics);
|
|
|
|
status = Tcl_Eval(pTcl, pBueffel);
|
|
if (status != TCL_OK) {
|
|
snprintf(self->scriptError, 510, "ERROR: Tcl subsystem reported %s",
|
|
Tcl_GetStringResult(pTcl));
|
|
self->parseOK = 0;
|
|
return NULL;
|
|
}
|
|
return (char *) Tcl_GetStringResult(pTcl);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
static int parseEntry(pConfigurableVirtualMotor self, char *entry)
|
|
{
|
|
RealMotor tuktuk;
|
|
char *pPtr = NULL;
|
|
char number[80], pError[256];
|
|
CommandList *pCom = NULL;
|
|
int status;
|
|
|
|
pPtr = entry;
|
|
pPtr = stptok(pPtr, tuktuk.name, 131, "=");
|
|
if (pPtr == NULL) {
|
|
snprintf(self->scriptError, 510, "ERROR: cannot interpret %s, %s",
|
|
entry, "require format: motor=value");
|
|
self->parseOK = 0;
|
|
return 0;
|
|
}
|
|
tuktuk.pDriv = (pIDrivable) FindDrivable(pServ->pSics, tuktuk.name);
|
|
pCom = FindCommand(pServ->pSics, tuktuk.name);
|
|
if (!pCom) {
|
|
snprintf(self->scriptError, 510, "ERROR: %s not found", tuktuk.name);
|
|
self->parseOK = 0;
|
|
return 0;
|
|
}
|
|
tuktuk.data = pCom->pData;
|
|
|
|
if (tuktuk.pDriv == NULL) {
|
|
snprintf(self->scriptError, 510, "ERROR: %s is not drivable",
|
|
tuktuk.name);
|
|
self->parseOK = 0;
|
|
return 0;
|
|
}
|
|
|
|
pPtr = stptok(pPtr, number, 79, "=");
|
|
tuktuk.value = atof(number);
|
|
|
|
LLDnodeAppendFrom(self->motorList, &tuktuk);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
static int parseCommandList(pConfigurableVirtualMotor self,
|
|
char *commandList)
|
|
{
|
|
char pEntry[256], *pPtr;
|
|
int status;
|
|
|
|
LLDdelete(self->motorList);
|
|
self->motorList = LLDcreate(sizeof(RealMotor));
|
|
|
|
pPtr = commandList;
|
|
while ((pPtr = stptok(pPtr, pEntry, 255, ",")) != NULL) {
|
|
status = parseEntry(self, pEntry);
|
|
if (status != 1) {
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
static int startMotorList(pConfigurableVirtualMotor self,
|
|
SConnection * pCon)
|
|
{
|
|
RealMotor tuktuk;
|
|
int status, iRet;
|
|
|
|
iRet = LLDnodePtr2First(self->motorList);
|
|
while (iRet != 0) {
|
|
LLDnodeDataTo(self->motorList, &tuktuk);
|
|
tuktuk.taskID = StartDriveTask(tuktuk.data,pCon,tuktuk.name,tuktuk.value);
|
|
if (tuktuk.taskID < 0) {
|
|
return HWFault;
|
|
}
|
|
tuktuk.running = 1;
|
|
LLDnodeDataFrom(self->motorList, &tuktuk);
|
|
iRet = LLDnodePtr2Next(self->motorList);
|
|
}
|
|
return OKOK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static long ConfSetValue(void *pData, SConnection * pCon, float newValue)
|
|
{
|
|
pConfigurableVirtualMotor self = (pConfigurableVirtualMotor) pData;
|
|
char *commandList = NULL;
|
|
int status;
|
|
|
|
assert(self != NULL);
|
|
|
|
commandList = invokeMotorScript(self, newValue);
|
|
if (commandList == NULL) {
|
|
SCWrite(pCon, self->scriptError, eError);
|
|
return 0;
|
|
}
|
|
|
|
status = parseCommandList(self, commandList);
|
|
if (status != 1) {
|
|
SCWrite(pCon, self->scriptError, eError);
|
|
return 0;
|
|
}
|
|
self->targetValue = newValue;
|
|
self->targetReached = 0;
|
|
self->posCount = 0;
|
|
self->last_report_time = 0.0;
|
|
|
|
status = startMotorList(self, pCon);
|
|
if (status != OKOK) {
|
|
HaltMotors(self);
|
|
}
|
|
return OKOK;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
static int ConfCheckLimits(void *pData, float fVal, char *error,
|
|
int errLen)
|
|
{
|
|
pConfigurableVirtualMotor self = (pConfigurableVirtualMotor) pData;
|
|
char *commandList = NULL;
|
|
int status, iRet;
|
|
RealMotor tuktuk;
|
|
|
|
assert(self != NULL);
|
|
|
|
if (self->targetValue != fVal) {
|
|
commandList = invokeMotorScript(self, fVal);
|
|
if (commandList == NULL) {
|
|
strlcpy(error, self->scriptError, errLen);
|
|
return 0;
|
|
}
|
|
|
|
status = parseCommandList(self, commandList);
|
|
if (status != 1) {
|
|
strlcpy(error, self->scriptError, errLen);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if(self->state != NULL){
|
|
free(self->state);
|
|
}
|
|
self->state = strdup("idle");
|
|
|
|
iRet = LLDnodePtr2First(self->motorList);
|
|
while (iRet != 0) {
|
|
LLDnodeDataTo(self->motorList, &tuktuk);
|
|
status =
|
|
tuktuk.pDriv->CheckLimits(tuktuk.data, tuktuk.value, error,
|
|
errLen);
|
|
if (status != 1) {
|
|
return status;
|
|
}
|
|
iRet = LLDnodePtr2Next(self->motorList);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static void KillInfo(void *pData)
|
|
{
|
|
pRegisteredInfo self = NULL;
|
|
|
|
assert(pData);
|
|
self = (pRegisteredInfo) pData;
|
|
if (self->pName) {
|
|
free(self->pName);
|
|
}
|
|
if (self->pCon) {
|
|
SCDeleteConnection(self->pCon);
|
|
}
|
|
free(self);
|
|
}
|
|
|
|
/*------------------- The CallBack function for interest ------------------
|
|
* iEvent: Event ID, see event.h for SICS events
|
|
* pEvent: May contain data from event generating object
|
|
* pUser: Data available when registering interest, see RegisteredInfo struct
|
|
* defined above for available info
|
|
--------------------------------------------------------------------------*/
|
|
static int InterestCallback(int iEvent, void *pEvent, void *pUser)
|
|
{
|
|
pRegisteredInfo pInfo = NULL;
|
|
char pBueffel[80];
|
|
EventInfo *pEventData;
|
|
|
|
assert(pEvent);
|
|
assert(pUser);
|
|
|
|
pEventData = (EventInfo *) pEvent;
|
|
pInfo = (RegisteredInfo *) pUser;
|
|
|
|
if (!SCisConnected(pInfo->pCon)) {
|
|
return -1;
|
|
}
|
|
|
|
if (pInfo->lastValue != pEventData->fVal) {
|
|
pInfo->lastValue = pEventData->fVal;
|
|
(pInfo->pCon)->conEventType = POSITION;
|
|
sprintf(pBueffel, "%s.position = %f ", pInfo->pName, pInfo->lastValue);
|
|
SCWrite(pInfo->pCon, pBueffel, eEvent);
|
|
}
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------*/
|
|
static void invokeCheckScript(pConfigurableVirtualMotor self,
|
|
SConnection * pCon)
|
|
{
|
|
Tcl_Interp *pTcl;
|
|
int status;
|
|
|
|
pTcl = InterpGetTcl(pServ->pSics);
|
|
|
|
if(self->checkScript != NULL){
|
|
status = Tcl_Eval(pTcl, self->checkScript);
|
|
if (status != TCL_OK) {
|
|
snprintf(self->scriptError, 510, "ERROR: Tcl subsystem reported %s",
|
|
Tcl_GetStringResult(pTcl));
|
|
SCWrite(pCon, self->scriptError, eError);
|
|
}
|
|
}
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static int ConfCheckStatus(void *pData, SConnection * pCon)
|
|
{
|
|
pConfigurableVirtualMotor self = (pConfigurableVirtualMotor) pData;
|
|
RealMotor tuktuk;
|
|
int iRet, status, result;
|
|
EventInfo event;
|
|
|
|
result = HWIdle;
|
|
iRet = LLDnodePtr2First(self->motorList);
|
|
while (iRet != 0) {
|
|
LLDnodeDataTo(self->motorList, &tuktuk);
|
|
if (tuktuk.running == 1) {
|
|
status = isTaskIDRunning(pServ->pTasker,tuktuk.taskID);
|
|
if(status == 1){
|
|
return HWBusy;
|
|
} else {
|
|
tuktuk.running = 0;
|
|
LLDnodeDataFrom(self->motorList, &tuktuk);
|
|
}
|
|
}
|
|
iRet = LLDnodePtr2Next(self->motorList);
|
|
}
|
|
|
|
if (result == HWIdle) {
|
|
/*
|
|
* Do we have to do another step? If so run it.
|
|
*/
|
|
if(strstr(self->state,"idle") == NULL){
|
|
status = ConfSetValue(self,pCon,self->targetValue);
|
|
if(status == OKOK){
|
|
result = HWBusy;
|
|
}
|
|
} else {
|
|
invokeCheckScript(self,pCon);
|
|
event.pName = self->name;
|
|
event.fVal = self->pDriv->GetValue(self, pCon);
|
|
InvokeCallBack(self->pCall, MOTDRIVE, &event);
|
|
}
|
|
} else if (result == HWBusy) {
|
|
double current_time, skip_time;
|
|
current_time = DoubleTime();
|
|
skip_time = 0.500;
|
|
if (self->last_report_time + skip_time <= current_time) {
|
|
event.pName = self->name;
|
|
event.fVal = self->pDriv->GetValue(self, pCon);
|
|
InvokeCallBack(self->pCall, MOTDRIVE, &event);
|
|
self->last_report_time = current_time;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------*/
|
|
static float invokeReadScript(pConfigurableVirtualMotor self,
|
|
SConnection * pCon)
|
|
{
|
|
Tcl_Interp *pTcl;
|
|
int status;
|
|
|
|
pTcl = InterpGetTcl(pServ->pSics);
|
|
|
|
status = Tcl_Eval(pTcl, self->readScript);
|
|
if (status != TCL_OK) {
|
|
snprintf(self->scriptError, 510, "ERROR: Tcl subsystem reported %s",
|
|
Tcl_GetStringResult(pTcl));
|
|
SCWrite(pCon, self->scriptError, eError);
|
|
}
|
|
return atof(Tcl_GetStringResult(pTcl));
|
|
}
|
|
|
|
/*---------------------------------------------------------------------*/
|
|
static void checkMotorValues(pConfigurableVirtualMotor self,
|
|
SConnection * pCon)
|
|
{
|
|
int iRet;
|
|
float value;
|
|
RealMotor tuktuk;
|
|
char pBueffel[512];
|
|
|
|
iRet = LLDnodePtr2First(self->motorList);
|
|
while (iRet != 0) {
|
|
LLDnodeDataTo(self->motorList, &tuktuk);
|
|
value = tuktuk.pDriv->GetValue(tuktuk.data, pCon);
|
|
value -= tuktuk.value;
|
|
if (value < .0) {
|
|
value *= -1;
|
|
}
|
|
if (value > .1) {
|
|
snprintf(pBueffel, 510, "WARNING: motor %s of position by %f",
|
|
tuktuk.name, value);
|
|
SCWrite(pCon, pBueffel, eWarning);
|
|
return;
|
|
}
|
|
iRet = LLDnodePtr2Next(self->motorList);
|
|
}
|
|
self->targetReached = 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
static float ConfGetValue(void *pData, SConnection * pCon)
|
|
{
|
|
pConfigurableVirtualMotor self = (pConfigurableVirtualMotor) pData;
|
|
float currentValue = BAD_VALUE;
|
|
|
|
assert(self != NULL);
|
|
|
|
if (self->readScript != NULL) {
|
|
currentValue = invokeReadScript(self, pCon);
|
|
} else {
|
|
if (self->targetReached == 1) {
|
|
return self->targetValue;
|
|
} else {
|
|
checkMotorValues(self, pCon);
|
|
if (self->targetReached) {
|
|
currentValue = self->targetValue;
|
|
}
|
|
}
|
|
}
|
|
return currentValue;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
static void *GetConfigurableVirtualMotorInterface(void *pData, int iID)
|
|
{
|
|
pConfigurableVirtualMotor self = NULL;
|
|
|
|
self = (pConfigurableVirtualMotor) pData;
|
|
assert(self);
|
|
if (iID == DRIVEID) {
|
|
return self->pDriv;
|
|
} else if (iID == CALLBACKINTERFACE) {
|
|
return self->pCall;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
static void KillConfigurableVirtualMotor(void *data)
|
|
{
|
|
pConfigurableVirtualMotor self = NULL;
|
|
|
|
self = (pConfigurableVirtualMotor) data;
|
|
if (self != NULL) {
|
|
if (self->pDes != NULL) {
|
|
DeleteDescriptor(self->pDes);
|
|
self->pDes = NULL;
|
|
}
|
|
LLDdelete(self->motorList);
|
|
if (self->name != NULL) {
|
|
free(self->name);
|
|
self->name = NULL;
|
|
}
|
|
if (self->scriptName != NULL) {
|
|
free(self->scriptName);
|
|
self->scriptName = NULL;
|
|
}
|
|
if (self->readScript != NULL) {
|
|
free(self->readScript);
|
|
self->readScript = NULL;
|
|
}
|
|
if(self->state != NULL){
|
|
free(self->state);
|
|
self->state = NULL;
|
|
}
|
|
if (self->pCall != NULL) {
|
|
DeleteCallBackInterface(self->pCall);
|
|
self->pCall = NULL;
|
|
}
|
|
if (self->pDriv != NULL) {
|
|
free(self->pDriv);
|
|
self->pDriv = NULL;
|
|
}
|
|
free(self);
|
|
self = NULL;
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
int MakeConfigurableVirtualMotor(SConnection * pCon, SicsInterp * pSics,
|
|
void *data, int argc, char *argv[])
|
|
{
|
|
pConfigurableVirtualMotor pNew = NULL;
|
|
char pBueffel[512];
|
|
|
|
if (argc < 2) {
|
|
SCWrite(pCon, "ERROR: need name to create configurable motor", eError);
|
|
return 0;
|
|
}
|
|
|
|
pNew =
|
|
(pConfigurableVirtualMotor) malloc(sizeof(ConfigurableVirtualMotor));
|
|
if (pNew == NULL) {
|
|
SCWrite(pCon, "ERROR: no memory to create configurable virtual motor",
|
|
eError);
|
|
return 0;
|
|
}
|
|
memset(pNew, 0, sizeof(ConfigurableVirtualMotor));
|
|
|
|
pNew->name = strdup(argv[1]);
|
|
pNew->posCount = 0;
|
|
pNew->last_report_time = 0.0;
|
|
pNew->pDes = CreateDescriptor("ConfigurableVirtualMotor");
|
|
pNew->pDriv = CreateDrivableInterface();
|
|
pNew->motorList = LLDcreate(sizeof(RealMotor));
|
|
if (pNew->pDes == NULL || pNew->pDriv == NULL || pNew->motorList < 0) {
|
|
SCWrite(pCon, "ERROR: no memory to create configurable virtual motor",
|
|
eError);
|
|
return 0;
|
|
}
|
|
pNew->state = strdup("idle");
|
|
|
|
/*
|
|
assign functions
|
|
*/
|
|
pNew->pDes->GetInterface = GetConfigurableVirtualMotorInterface;
|
|
pNew->pDriv->Halt = HaltMotors;
|
|
pNew->pDriv->CheckLimits = ConfCheckLimits;
|
|
pNew->pDriv->SetValue = ConfSetValue;
|
|
pNew->pDriv->CheckStatus = ConfCheckStatus;
|
|
pNew->pDriv->GetValue = ConfGetValue;
|
|
|
|
/* initialise callback interface */
|
|
pNew->pCall = CreateCallBackInterface();
|
|
if (!pNew->pCall) {
|
|
KillConfigurableVirtualMotor(pNew);
|
|
return 0;
|
|
}
|
|
/*
|
|
install command
|
|
*/
|
|
if (AddCommand(pSics, argv[1], ConfigurableVirtualMotorAction,
|
|
KillConfigurableVirtualMotor, pNew) != 1) {
|
|
snprintf(pBueffel, 510, "ERROR: duplicate command %s not created",
|
|
argv[1]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
} else {
|
|
SCSendOK(pCon);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
int ConfigurableVirtualMotorAction(SConnection * pCon, SicsInterp * pSics,
|
|
void *data, int argc, char *argv[])
|
|
{
|
|
pConfigurableVirtualMotor self = NULL;
|
|
char pBueffel[512];
|
|
float value;
|
|
long lID;
|
|
pRegisteredInfo pRegInfo = NULL;
|
|
|
|
self = (pConfigurableVirtualMotor) data;
|
|
assert(self != NULL);
|
|
|
|
if (argc > 1) {
|
|
strtolower(argv[1]);
|
|
if (strcmp(argv[1], "drivescript") == 0) {
|
|
if (argc > 2) {
|
|
/* set case */
|
|
Arg2Text(argc - 2, &argv[2], pBueffel, 510);
|
|
self->scriptName = strdup(pBueffel);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
/* inquiry */
|
|
if (self->scriptName == NULL) {
|
|
snprintf(pBueffel, 510, "%s.drivescript = UNDEFINED", argv[0]);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
} else {
|
|
snprintf(pBueffel, 510, "%s.drivescript = %s", argv[0],
|
|
self->scriptName);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
}
|
|
} else if (strcmp(argv[1], "readscript") == 0) {
|
|
if (argc > 2) {
|
|
/* set case */
|
|
Arg2Text(argc - 2, &argv[2], pBueffel, 510);
|
|
self->readScript = strdup(pBueffel);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
/* inquiry */
|
|
if (self->readScript == NULL) {
|
|
snprintf(pBueffel, 510, "%s.readscript = UNDEFINED", argv[0]);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
} else {
|
|
snprintf(pBueffel, 510, "%s.readscript = %s", argv[0],
|
|
self->readScript);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
}
|
|
} else if (strcmp(argv[1], "checkscript") == 0) {
|
|
if (argc > 2) {
|
|
/* set case */
|
|
Arg2Text(argc - 2, &argv[2], pBueffel, 510);
|
|
self->checkScript = strdup(pBueffel);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
/* inquiry */
|
|
if (self->checkScript == NULL) {
|
|
snprintf(pBueffel, 510, "%s.checkscript = UNDEFINED", argv[0]);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
} else {
|
|
snprintf(pBueffel, 510, "%s.checkscript = %s", argv[0],
|
|
self->checkScript);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
}
|
|
} else if (strcmp(argv[1], "state") == 0) {
|
|
if (argc > 2) {
|
|
/* set case */
|
|
Arg2Text(argc - 2, &argv[2], pBueffel, 510);
|
|
if(self->state != NULL){
|
|
free(self->state);
|
|
}
|
|
self->state = strdup(pBueffel);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
/* inquiry */
|
|
if (self->state == NULL) {
|
|
snprintf(pBueffel, 510, "%s.state = UNDEFINED", argv[0]);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
} else {
|
|
snprintf(pBueffel, 510, "%s.state = %s", argv[0],
|
|
self->state);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
}
|
|
} else if (strcmp(argv[1], "target") == 0) {
|
|
/* inquiry */
|
|
snprintf(pBueffel, 510, "%s.target = %f", argv[0], self->targetValue);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "interest") == 0) {
|
|
pRegInfo = (pRegisteredInfo) malloc(sizeof(RegisteredInfo));
|
|
if (!pRegInfo) {
|
|
SCWrite(pCon, "ERROR: out of memory in confvirtualmot.c", eError);
|
|
return 0;
|
|
}
|
|
pRegInfo->pName = strdup(argv[0]);
|
|
pRegInfo->pCon = SCCopyConnection(pCon);
|
|
value = ConfGetValue(self, pCon);
|
|
if (value < -9990.) {
|
|
snprintf(pBueffel,511,
|
|
"Failed to register interest, Reason:Error obtaining current position for %s",
|
|
argv[0]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
pRegInfo->lastValue = value;
|
|
|
|
RemoveCallbackUsr(self->pCall, InterestCallback, CheckMotiMatch, pCon); /* only this one */
|
|
lID = RegisterCallback(self->pCall, MOTDRIVE,
|
|
InterestCallback, pRegInfo, KillInfo);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else if(strcmp(argv[1],"uninterest") == 0) {
|
|
RemoveCallbackUsr(self->pCall, InterestCallback, CheckMotiMatch, pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
snprintf(pBueffel, sizeof(pBueffel), "ERROR: subcommand %s to %s unknown",
|
|
argv[1], argv[0]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
} else {
|
|
value = self->pDriv->GetValue(self, pCon);
|
|
snprintf(pBueffel, 510, "%s = %f", argv[0], value);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
}
|