- Extended confvirtmot to allow for sequences of calls
- Extended confvirtmot to have a checkscript - Made sure that targets get updated when calling tasdrive - Fixed some output codes in tasdrive.c - Made tdchm invoke counters event message for Melone - Fixed the ConID inefficiency by caching the host name in asynnet.c - Added a traceActive function to trace SKIPPED: psi/tdchm.c
This commit is contained in:
20
asynnet.c
20
asynnet.c
@ -57,6 +57,7 @@ typedef struct {
|
||||
ANETcallback readCallback;
|
||||
void *userData;
|
||||
ANETkill killUser;
|
||||
char host[132];
|
||||
} SocketDescriptor, *pSocketDescriptor;
|
||||
|
||||
static SocketDescriptor connections[MAXCONNECTIONS];
|
||||
@ -480,16 +481,19 @@ int ANETinfo(int handle, char *hostname, int hostnameLen)
|
||||
if (con == NULL) {
|
||||
return ANETDISCONNECTED;
|
||||
} else {
|
||||
len = sizeof sin;
|
||||
if (getpeername(con->socket, (struct sockaddr *) &sin, &len) < 0) {
|
||||
return ANETSOCKERROR;
|
||||
}
|
||||
if ((host = gethostbyaddr((char *) &sin.sin_addr,
|
||||
sizeof(sin.sin_addr), AF_INET)) == NULL) {
|
||||
return ANETSOCKERROR;
|
||||
if(strlen(con->host) < 3){
|
||||
len = sizeof sin;
|
||||
if (getpeername(con->socket, (struct sockaddr *) &sin, &len) < 0) {
|
||||
return ANETSOCKERROR;
|
||||
}
|
||||
if ((host = gethostbyaddr((char *) &sin.sin_addr,
|
||||
sizeof(sin.sin_addr), AF_INET)) == NULL) {
|
||||
return ANETSOCKERROR;
|
||||
}
|
||||
strlcpy(con->host,host->h_name, 132);
|
||||
}
|
||||
memset(hostname, 0, hostnameLen);
|
||||
strlcpy(hostname, host->h_name, hostnameLen);
|
||||
strlcpy(hostname, con->host, hostnameLen);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ typedef struct __CONFVIRTMOT {
|
||||
char *scriptName;
|
||||
char *readScript;
|
||||
char *checkScript;
|
||||
char *state;
|
||||
int motorList;
|
||||
float targetValue;
|
||||
int targetReached;
|
||||
|
@ -9,6 +9,22 @@
|
||||
|
||||
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 pu the baldes 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 doen in repetition until the
|
||||
writescript sets state to idle again.
|
||||
|
||||
Mark Koennecke, April 2012
|
||||
-------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
@ -299,7 +315,7 @@ static void invokeCheckScript(pConfigurableVirtualMotor self,
|
||||
pTcl = InterpGetTcl(pServ->pSics);
|
||||
|
||||
if(self->checkScript != NULL){
|
||||
status = Tcl_Eval(pTcl, self->readScript);
|
||||
status = Tcl_Eval(pTcl, self->checkScript);
|
||||
if (status != TCL_OK) {
|
||||
snprintf(self->scriptError, 510, "ERROR: Tcl subsystem reported %s",
|
||||
Tcl_GetStringResult(pTcl));
|
||||
@ -331,6 +347,10 @@ static int ConfCheckStatus(void *pData, SConnection * pCon)
|
||||
break;
|
||||
case HWFault:
|
||||
case HWPosFault:
|
||||
if(self->state != NULL){
|
||||
free(self->state);
|
||||
self->state = strdup("idle");
|
||||
}
|
||||
return status;
|
||||
break;
|
||||
default:
|
||||
@ -344,10 +364,20 @@ static int ConfCheckStatus(void *pData, SConnection * pCon)
|
||||
}
|
||||
|
||||
if (result == HWIdle) {
|
||||
invokeCheckScript(self,pCon);
|
||||
event.pName = self->name;
|
||||
event.fVal = self->pDriv->GetValue(self, pCon);
|
||||
InvokeCallBack(self->pCall, MOTDRIVE, &event);
|
||||
/*
|
||||
* 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) {
|
||||
self->posCount++;
|
||||
if (self->posCount >= 10 /*ObVal(self->ParArray,MOVECOUNT) */ ) {
|
||||
@ -468,6 +498,10 @@ static void KillConfigurableVirtualMotor(void *data)
|
||||
free(self->readScript);
|
||||
self->readScript = NULL;
|
||||
}
|
||||
if(self->state != NULL){
|
||||
free(self->state);
|
||||
self->state = NULL;
|
||||
}
|
||||
free(self);
|
||||
self = NULL;
|
||||
}
|
||||
@ -504,6 +538,7 @@ int MakeConfigurableVirtualMotor(SConnection * pCon, SicsInterp * pSics,
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
pNew->state = strdup("idle");
|
||||
|
||||
/*
|
||||
assign functions
|
||||
@ -613,6 +648,31 @@ int ConfigurableVirtualMotorAction(SConnection * pCon, SicsInterp * pSics,
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} else if (strcmp(argv[1], "state") == 0) {
|
||||
if (argc > 2) {
|
||||
/* set case */
|
||||
Arg2Text(argc - 2, &argv[2], pBueffel, 510);
|
||||
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) {
|
||||
|
@ -17,6 +17,7 @@ typedef struct __CONFVIRTMOT {
|
||||
char *scriptName;
|
||||
char *readScript;
|
||||
char *checkScript;
|
||||
char *state;
|
||||
int motorList;
|
||||
float targetValue;
|
||||
int targetReached;
|
||||
|
12
devexec.c
12
devexec.c
@ -280,7 +280,7 @@ void ExeInterest(pExeList self, pDevEntry pDev, char *text)
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static void InvokeNewTarget(pExeList self, char *name, float target)
|
||||
void InvokeNewTarget(pExeList self, char *name, float target)
|
||||
{
|
||||
NewTarget targetEvent;
|
||||
|
||||
@ -772,25 +772,35 @@ int CheckExeList(pExeList self)
|
||||
iRet = LLDnodePtr2First(self->iList);
|
||||
return testFinish(self);
|
||||
}
|
||||
/*--------------------------------------------------------------------------
|
||||
Cludge to not move the current pointer for CheckExeList
|
||||
*/
|
||||
void *LLDgetCurrent(int List);
|
||||
void LLDsetCurrent(int List, void *pointer);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int DevExecLevelRunning(pExeList self, int level)
|
||||
{
|
||||
int iRet;
|
||||
pDevEntry pDev = NULL;
|
||||
void *current;
|
||||
|
||||
if(self->lTask < 0){
|
||||
return 0;
|
||||
}
|
||||
current = LLDgetCurrent(self->iList);
|
||||
iRet = LLDnodePtr2First(self->iList);
|
||||
while (iRet != 0) {
|
||||
LLDnodeDataTo(self->iList, &pDev);
|
||||
if (pDev) {
|
||||
if(pDev->level >= level){
|
||||
LLDsetCurrent(self->iList,current);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
iRet = LLDnodePtr2Next(self->iList);
|
||||
}
|
||||
LLDsetCurrent(self->iList,current);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
18
lld.c
18
lld.c
@ -22,6 +22,14 @@
|
||||
- Node deletion via first and/or last node pointers.
|
||||
(as for access functions, then simplify ...)
|
||||
|
||||
** Comment by Mark Koennecke **
|
||||
This implementation has problems when being accessed
|
||||
concurrently in any form. The reason is the single
|
||||
current pointer in the list data stucture. A improvement
|
||||
would be to have a function to get an iterator which holds
|
||||
this crucial value and functions to iterate on the iterator
|
||||
*************** end of comment *********
|
||||
|
||||
_____ This version is Public Domain.
|
||||
/_|__| A.Reitsma, Delft, The Netherlands.
|
||||
/ | \ --------------------------------------------------------------- */
|
||||
@ -647,3 +655,13 @@ int LLDnodeDataFrom(int List, void *source)
|
||||
}
|
||||
|
||||
/* ==== LLD.c end ==================================================== */
|
||||
/**
|
||||
* These two functions help me implement a solution for a race condition
|
||||
* in devexec.c, especially in DevexecLevelRunning.
|
||||
*/
|
||||
void *LLDgetCurrent(int List){
|
||||
return ListControl[List].current;
|
||||
}
|
||||
void LLDsetCurrent(int List, void *pointer){
|
||||
ListControl[List].current = (struct Node*)pointer;
|
||||
}
|
||||
|
9
motor.c
9
motor.c
@ -364,6 +364,7 @@ static void finishDriving(pMotor self, SConnection * pCon)
|
||||
InvokeCallBack(self->pCall, MOTDRIVE, &sCall); /* send also very last position */
|
||||
InvokeCallBack(self->pCall, MOTEND, &sCall);
|
||||
tracePar(self->name,"%f",sCall.fVal);
|
||||
self->running = 0;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
@ -484,6 +485,10 @@ static int MotorStatus(void *sulf, SConnection * pCon)
|
||||
assert(sulf);
|
||||
self = (pMotor) sulf;
|
||||
|
||||
if(self->running != 1){
|
||||
return HWIdle;
|
||||
}
|
||||
|
||||
status = evaluateStatus(self, pCon);
|
||||
if (self->pDrivInt->drivableStatus != status) {
|
||||
((SConnection *) pCon)->conEventType = STATUS;
|
||||
@ -752,10 +757,12 @@ static long MotorRunImpl(void *sulf, SConnection * pCon, float fNew)
|
||||
case MOTREDO:
|
||||
iRet = self->pDriver->RunTo(self->pDriver, fHard);
|
||||
if (iRet == OKOK) {
|
||||
self->running = 1;
|
||||
return OKOK;
|
||||
}
|
||||
break;
|
||||
case MOTOK:
|
||||
self->running = 1;
|
||||
return OKOK;
|
||||
break;
|
||||
}
|
||||
@ -766,6 +773,7 @@ static long MotorRunImpl(void *sulf, SConnection * pCon, float fNew)
|
||||
SCSetInterrupt(pCon, (int) ObVal(self->ParArray, INT));
|
||||
return HWFault;
|
||||
}
|
||||
self->running = 1;
|
||||
return OKOK;
|
||||
}
|
||||
|
||||
@ -1109,6 +1117,7 @@ void MotorReset(pMotor pM)
|
||||
usUser);
|
||||
ObParInit(pM->ParArray, SZERO, "softzero", ZEROINACTIVE, usUser);
|
||||
ObParInit(pM->ParArray, FIX, "fixed", -1, usUser);
|
||||
pM->running = 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
1
motor.h
1
motor.h
@ -38,6 +38,7 @@ typedef struct __Motor {
|
||||
int posFaultCount;
|
||||
int stopped;
|
||||
int errorCount;
|
||||
int running;
|
||||
ObPar *ParArray;
|
||||
void *pPrivate;
|
||||
void (*KillPrivate) (void *);
|
||||
|
@ -472,6 +472,13 @@ static char *SctActionHandler(void *actionData, char *lastReply,
|
||||
SCPrintf(con, eError,
|
||||
"ERROR: action {%s} in {%s} node %s:\nERROR: %s",
|
||||
data->name, origScript, path, result);
|
||||
if(data != NULL && data->controller != NULL){
|
||||
traceIO(data->controller->node->name, "ERROR: action {%s} in {%s} node %s:\nERROR: %s",
|
||||
data->name, origScript, path, result);
|
||||
} else {
|
||||
traceIO("sctunknown", "reply:%s", "ERROR: action {%s} in {%s} node %s:\nERROR: %s",
|
||||
data->name, origScript, path, result);
|
||||
}
|
||||
}
|
||||
snprintf(msg, sizeof msg, "{%s} %s", origScript, result);
|
||||
if (strcasecmp(data->name, "read") == 0) {
|
||||
@ -776,13 +783,14 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData,
|
||||
*/
|
||||
SCDeleteConnection(data->conCtx);
|
||||
}
|
||||
DeleteDynString(text);
|
||||
data->conCtx = SCCopyConnection(con);
|
||||
data->answered = 0;
|
||||
data->inMacro = SCinMacro(con);
|
||||
tracePar(node->name,"Queued %s to %s",node->name, GetCharArray(text));
|
||||
DevQueue(data->controller->devser, data, prio,
|
||||
SctWriteHandler, SctMatch, NULL, SctDataInfo);
|
||||
/* no kill function in DevQueue: data is owned by the node (callback list) */
|
||||
DeleteDynString(text);
|
||||
return hdbContinue;
|
||||
}
|
||||
|
||||
|
2
sicvar.c
2
sicvar.c
@ -533,7 +533,7 @@ int VarWrapper(SConnection * pCon, SicsInterp * pInterp, void *pData,
|
||||
Undocumented feauture: force a set even while driving etc.
|
||||
Internal privilege required to do this.
|
||||
*/
|
||||
if (!SCMatchRights(pCon, usInternal)) {
|
||||
if (!SCMatchRights(pCon, usUser)) {
|
||||
return 0;
|
||||
}
|
||||
pCurrent = pCurrent->pNext;
|
||||
|
35
tasdrive.c
35
tasdrive.c
@ -43,7 +43,7 @@ static long TASSetValue(void *pData, SConnection * pCon, float value)
|
||||
|
||||
if (self->code > 5 && self->math->tasMode == ELASTIC) {
|
||||
SCWrite(pCon, "ERROR: cannot drive this motor in elastic mode",
|
||||
eError);
|
||||
eLogError);
|
||||
return HWFault;
|
||||
}
|
||||
setTasPar(&self->math->target, self->math->tasMode, self->code, value);
|
||||
@ -146,7 +146,7 @@ static float TASGetValue(void *pData, SConnection * pCon)
|
||||
&self->math->current);
|
||||
if (status < 0) {
|
||||
SCWrite(pCon, "ERROR: out of memory calculating Q-E variables",
|
||||
eError);
|
||||
eLogError);
|
||||
return -999.99;
|
||||
}
|
||||
if (self->math->tasMode == ELASTIC) {
|
||||
@ -182,7 +182,7 @@ static float TASQMGetValue(void *pData, SConnection * pCon)
|
||||
angles, &self->math->current);
|
||||
if (status < 0) {
|
||||
SCWrite(pCon, "ERROR: out of memory calculating Q-E variables",
|
||||
eError);
|
||||
eLogError);
|
||||
return -999.99;
|
||||
}
|
||||
if (self->math->tasMode == ELASTIC) {
|
||||
@ -250,6 +250,8 @@ static float getMotorValue(pMotor mot, SConnection * pCon)
|
||||
GetDrivablePosition(mot, pCon, &val);
|
||||
return val;
|
||||
}
|
||||
/*--------------------- In devexec.c --------------------------------------*/
|
||||
void InvokeNewTarget(pExeList self, char *name, float target);
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int startTASMotor(pMotor mot, SConnection * pCon, char *name,
|
||||
@ -268,20 +270,25 @@ static int startTASMotor(pMotor mot, SConnection * pCon, char *name,
|
||||
MotorGetPar(mot, "fixed", &fixed);
|
||||
if (ABS(fixed - 1.0) < .1) {
|
||||
snprintf(buffer, 131, "WARNING: %s is FIXED", name);
|
||||
SCWrite(pCon, buffer, eWarning);
|
||||
SCWrite(pCon, buffer, eLog);
|
||||
return OKOK;
|
||||
}
|
||||
}
|
||||
mot->stopped = 0;
|
||||
if (ABS(val - target) > MOTPREC) {
|
||||
pDriv = GetDrivableInterface(mot);
|
||||
SCStartBuffering(pCon);
|
||||
/* SCStartBuffering(pCon); */
|
||||
status = pDriv->SetValue(mot, pCon, (float) target);
|
||||
mes = SCEndBuffering(pCon);
|
||||
/*
|
||||
to force updates on targets
|
||||
*/
|
||||
InvokeNewTarget(pServ->pExecutor, name, target);
|
||||
/*mes = SCEndBuffering(pCon);
|
||||
if (status != OKOK) {
|
||||
SCPrintf(pCon,eLogError, GetCharArray(mes));
|
||||
return status;
|
||||
}
|
||||
*/
|
||||
}
|
||||
writeMotPos(pCon, silent, name, val, target);
|
||||
return status;
|
||||
@ -316,7 +323,7 @@ static int startMotors(ptasMot self, tasAngles angles,
|
||||
status = startTASMotor(self->math->motors[MCV], pCon, "mcv",
|
||||
curve, silent);
|
||||
if (status != OKOK) {
|
||||
SCWrite(pCon,"WARNING: monochromator vertical curvature motor failed to start", eWarning);
|
||||
SCWrite(pCon,"WARNING: monochromator vertical curvature motor failed to start", eLog);
|
||||
SCSetInterrupt(pCon,eContinue);
|
||||
}
|
||||
}
|
||||
@ -327,7 +334,7 @@ static int startMotors(ptasMot self, tasAngles angles,
|
||||
status = startTASMotor(self->math->motors[MCH], pCon, "mch",
|
||||
curve, silent);
|
||||
if (status != OKOK) {
|
||||
SCWrite(pCon,"WARNING: monochromator horizontal curvature motor failed to start", eWarning);
|
||||
SCWrite(pCon,"WARNING: monochromator horizontal curvature motor failed to start", eLog);
|
||||
SCSetInterrupt(pCon,eContinue);
|
||||
}
|
||||
}
|
||||
@ -354,7 +361,7 @@ static int startMotors(ptasMot self, tasAngles angles,
|
||||
status = startTASMotor(self->math->motors[ACV], pCon, "acv",
|
||||
curve, silent);
|
||||
if (status != OKOK) {
|
||||
SCWrite(pCon,"WARNING: analyzer vertical curvature motor failed to start", eWarning);
|
||||
SCWrite(pCon,"WARNING: analyzer vertical curvature motor failed to start", eLog);
|
||||
SCSetInterrupt(pCon,eContinue);
|
||||
}
|
||||
}
|
||||
@ -364,7 +371,7 @@ static int startMotors(ptasMot self, tasAngles angles,
|
||||
status = startTASMotor(self->math->motors[ACH], pCon, "ach",
|
||||
curve, silent);
|
||||
if (status != OKOK) {
|
||||
SCWrite(pCon,"WARNING: analyzer horizontal curvature motor failed to start", eWarning);
|
||||
SCWrite(pCon,"WARNING: analyzer horizontal curvature motor failed to start", eLog);
|
||||
SCSetInterrupt(pCon,eContinue);
|
||||
}
|
||||
}
|
||||
@ -422,7 +429,7 @@ static int checkQMotorLimits(ptasMot self, SConnection * pCon,
|
||||
if (status != 1) {
|
||||
retVal = 0;
|
||||
snprintf(pBueffel, 256, "ERROR: limit violation an a3: %s", error);
|
||||
SCWrite(pCon, pBueffel, eError);
|
||||
SCWrite(pCon, pBueffel, eLogError);
|
||||
}
|
||||
}
|
||||
|
||||
@ -434,7 +441,7 @@ static int checkQMotorLimits(ptasMot self, SConnection * pCon,
|
||||
if (status != 1) {
|
||||
retVal = 0;
|
||||
snprintf(pBueffel, 256, "ERROR: limit violation an a4: %s", error);
|
||||
SCWrite(pCon, pBueffel, eError);
|
||||
SCWrite(pCon, pBueffel, eLogError);
|
||||
}
|
||||
|
||||
if (driveTilt == 1) {
|
||||
@ -445,7 +452,7 @@ static int checkQMotorLimits(ptasMot self, SConnection * pCon,
|
||||
if (status != 1) {
|
||||
retVal = 0;
|
||||
snprintf(pBueffel, 256, "ERROR: limit violation an SGU: %s", error);
|
||||
SCWrite(pCon, pBueffel, eError);
|
||||
SCWrite(pCon, pBueffel, eLogError);
|
||||
}
|
||||
|
||||
pDrivInt = GetDrivableInterface(self->math->motors[SGL]);
|
||||
@ -455,7 +462,7 @@ static int checkQMotorLimits(ptasMot self, SConnection * pCon,
|
||||
if (status != 1) {
|
||||
retVal = 0;
|
||||
snprintf(pBueffel, 256, "ERROR: limit violation an SGL: %s", error);
|
||||
SCWrite(pCon, pBueffel, eError);
|
||||
SCWrite(pCon, pBueffel, eLogError);
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
|
9
trace.c
9
trace.c
@ -31,6 +31,15 @@ static int hdbInit = 0;
|
||||
static int filterProv = 0;
|
||||
static int debug = 0;
|
||||
/*----------------------------------------------------------------------------------------*/
|
||||
int traceActive()
|
||||
{
|
||||
if (log == NULL){
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------------------------*/
|
||||
static char *GetTracePath(pHdb node)
|
||||
{
|
||||
pHdb nodeStack[64];
|
||||
|
Reference in New Issue
Block a user