- More debugging of scriptcontext, mostly working now
- Created driveable SICSobj for standalone and as an adapter
This commit is contained in:
17
ascon.c
17
ascon.c
@ -117,7 +117,13 @@ static void AsconConnect(Ascon *a) {
|
|||||||
fcntl(a->fd, F_SETFL, oldopts | O_NONBLOCK);
|
fcntl(a->fd, F_SETFL, oldopts | O_NONBLOCK);
|
||||||
ret = connect(a->fd, (struct sockaddr *)&adr, sizeof(struct sockaddr_in));
|
ret = connect(a->fd, (struct sockaddr *)&adr, sizeof(struct sockaddr_in));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (errno != EINPROGRESS) {
|
switch(errno) {
|
||||||
|
case EINPROGRESS:
|
||||||
|
case EALREADY:
|
||||||
|
case EISCONN:
|
||||||
|
a->state = AsconConnecting;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
AsconError(a, "connect failed:", errno);
|
AsconError(a, "connect failed:", errno);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -289,6 +295,9 @@ int AsconStdHandler(Ascon *a) {
|
|||||||
DynStringConcat(a->wrBuffer, a->sendTerminator);
|
DynStringConcat(a->wrBuffer, a->sendTerminator);
|
||||||
a->wrPos = 0;
|
a->wrPos = 0;
|
||||||
a->state = AsconWriting;
|
a->state = AsconWriting;
|
||||||
|
if(strstr(GetCharArray(a->wrBuffer),"@@NOSEND@@") != NULL){
|
||||||
|
a->state = AsconWriteDone;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case AsconWriting:
|
case AsconWriting:
|
||||||
AsconReadGarbage(a->fd);
|
AsconReadGarbage(a->fd);
|
||||||
@ -296,6 +305,10 @@ int AsconStdHandler(Ascon *a) {
|
|||||||
ret = AsconWriteChars(a->fd, GetCharArray(a->wrBuffer) + a->wrPos, l);
|
ret = AsconWriteChars(a->fd, GetCharArray(a->wrBuffer) + a->wrPos, l);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
AsconError(a, "send failed:", errno);
|
AsconError(a, "send failed:", errno);
|
||||||
|
/*
|
||||||
|
* Ooops: which state shall we go to after a write fail?
|
||||||
|
* This seems to retry.
|
||||||
|
*/
|
||||||
} else {
|
} else {
|
||||||
a->wrPos += ret;
|
a->wrPos += ret;
|
||||||
if (a->wrPos >= GetDynStringLength(a->wrBuffer)) {
|
if (a->wrPos >= GetDynStringLength(a->wrBuffer)) {
|
||||||
@ -476,6 +489,8 @@ AsconStatus AsconTask(Ascon *a) {
|
|||||||
now = DoubleTime();
|
now = DoubleTime();
|
||||||
if (now > a->lastReconnect + a->reconnectInterval) {
|
if (now > a->lastReconnect + a->reconnectInterval) {
|
||||||
a->lastReconnect = now;
|
a->lastReconnect = now;
|
||||||
|
close(a->fd);
|
||||||
|
a->fd = -1;
|
||||||
a->state = AsconConnectStart;
|
a->state = AsconConnectStart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
5
devser.c
5
devser.c
@ -74,6 +74,7 @@ DevAction *DevNextAction(DevSer *devser) {
|
|||||||
double now;
|
double now;
|
||||||
SchedHeader *header;
|
SchedHeader *header;
|
||||||
|
|
||||||
|
|
||||||
devser->current = NULL;
|
devser->current = NULL;
|
||||||
if (devser->actions) {
|
if (devser->actions) {
|
||||||
prio = devser->actions->prio;
|
prio = devser->actions->prio;
|
||||||
@ -125,6 +126,7 @@ int DevQueueTask(void *ds) {
|
|||||||
if (action == NULL) {
|
if (action == NULL) {
|
||||||
action = DevNextAction(devser);
|
action = DevNextAction(devser);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (action != NULL) {
|
while (action != NULL) {
|
||||||
status = AsconTask(devser->asyncConn);
|
status = AsconTask(devser->asyncConn);
|
||||||
if (status == AsconFailure) {
|
if (status == AsconFailure) {
|
||||||
@ -226,7 +228,7 @@ void DevQueue(DevSer *devser, void *actionData, DevPrio prio,
|
|||||||
ptr2Last = &devser->actions;
|
ptr2Last = &devser->actions;
|
||||||
for (action = devser->actions; action != NULL && action->prio >= prio; action = action->next) {
|
for (action = devser->actions; action != NULL && action->prio >= prio; action = action->next) {
|
||||||
if (action->hdl == hdl && matchFunc(actionData, action->data)) {
|
if (action->hdl == hdl && matchFunc(actionData, action->data)) {
|
||||||
return; /* there is already an identic action */
|
return; /* there is already an identical action */
|
||||||
}
|
}
|
||||||
ptr2Last = &action->next;
|
ptr2Last = &action->next;
|
||||||
}
|
}
|
||||||
@ -330,6 +332,7 @@ int DevRemoveAction(DevSer *devser, void *actionData) {
|
|||||||
DevAction *action = NULL;
|
DevAction *action = NULL;
|
||||||
int cnt=0;
|
int cnt=0;
|
||||||
|
|
||||||
|
|
||||||
/* Remove current action, if matched. If a reply is pending, the next action will
|
/* Remove current action, if matched. If a reply is pending, the next action will
|
||||||
get the reply. But as in the inital state no reply is expected, this should not harm. */
|
get the reply. But as in the inital state no reply is expected, this should not harm. */
|
||||||
action = devser->current;
|
action = devser->current;
|
||||||
|
42
fomerge.c
42
fomerge.c
@ -689,10 +689,8 @@ static int TOFLambda(SicsInterp *pSics, SConnection *pCon,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
static int putElastic(SicsInterp *pSics, SConnection *pCon,
|
static float calcElastic(SicsInterp *pSics, SConnection *pCon)
|
||||||
pNXScript pNexus, char *alias, float fElastic)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
int status, iTime, iDet, i;
|
int status, iTime, iDet, i;
|
||||||
const float *fTimeBin = NULL;
|
const float *fTimeBin = NULL;
|
||||||
int *sum = NULL;
|
int *sum = NULL;
|
||||||
@ -706,7 +704,7 @@ static int putElastic(SicsInterp *pSics, SConnection *pCon,
|
|||||||
SCWrite(pCon,
|
SCWrite(pCon,
|
||||||
"ERROR: need middle detector bank for elastic peak calculation",
|
"ERROR: need middle detector bank for elastic peak calculation",
|
||||||
eError);
|
eError);
|
||||||
return NX_ERROR;
|
return -1.;
|
||||||
}
|
}
|
||||||
fTimeBin = GetHistTimeBin(pMem,&iTime);
|
fTimeBin = GetHistTimeBin(pMem,&iTime);
|
||||||
iDet = getFMdim(MIDDLE);
|
iDet = getFMdim(MIDDLE);
|
||||||
@ -715,7 +713,7 @@ static int putElastic(SicsInterp *pSics, SConnection *pCon,
|
|||||||
{
|
{
|
||||||
SCWrite(pCon,"ERROR: out of memory calculating elastic peak position",
|
SCWrite(pCon,"ERROR: out of memory calculating elastic peak position",
|
||||||
eError);
|
eError);
|
||||||
return NX_ERROR;
|
return -1;
|
||||||
}
|
}
|
||||||
if(fitter == NULL)
|
if(fitter == NULL)
|
||||||
{
|
{
|
||||||
@ -723,7 +721,7 @@ static int putElastic(SicsInterp *pSics, SConnection *pCon,
|
|||||||
if(!fitter)
|
if(!fitter)
|
||||||
{
|
{
|
||||||
SCWrite(pCon,"ERROR: cannot allocate fitting structure",eError);
|
SCWrite(pCon,"ERROR: cannot allocate fitting structure",eError);
|
||||||
return NX_ERROR;
|
return -1.;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -734,7 +732,7 @@ static int putElastic(SicsInterp *pSics, SConnection *pCon,
|
|||||||
{
|
{
|
||||||
SCWrite(pCon,"ERROR: out of memory in putElastic",eError);
|
SCWrite(pCon,"ERROR: out of memory in putElastic",eError);
|
||||||
free(sum);
|
free(sum);
|
||||||
return NX_ERROR;
|
return -1.;
|
||||||
}
|
}
|
||||||
for(i = 0; i < iTime; i++)
|
for(i = 0; i < iTime; i++)
|
||||||
{
|
{
|
||||||
@ -743,20 +741,26 @@ static int putElastic(SicsInterp *pSics, SConnection *pCon,
|
|||||||
status = CalculateFitFromData(fitter,(float *)fTimeBin,lSum,iTime);
|
status = CalculateFitFromData(fitter,(float *)fTimeBin,lSum,iTime);
|
||||||
free(lSum);
|
free(lSum);
|
||||||
GetFitResults(fitter,&fCenter,&fStdDev,&fFWHM,&fVal);
|
GetFitResults(fitter,&fCenter,&fStdDev,&fFWHM,&fVal);
|
||||||
fVal = fCenter - fElastic;
|
|
||||||
if(fVal < 0.)
|
|
||||||
fVal = - fVal;
|
|
||||||
/* bad value, leave at theoretical value */
|
|
||||||
if(fVal < 10.)
|
|
||||||
{
|
|
||||||
fElastic = fCenter;
|
|
||||||
}
|
|
||||||
free(sum);
|
free(sum);
|
||||||
|
return fCenter;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
#define ABS(x) (x < 0 ? -(x) : (x))
|
||||||
|
|
||||||
|
static int putElastic(SicsInterp *pSics, SConnection *pCon,
|
||||||
|
pNXScript pNexus, char *alias, float fElastic)
|
||||||
|
{
|
||||||
|
float fCalc;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
fCalc = calcElastic(pSics,pCon);
|
||||||
|
if(ABS(fElastic -fCalc) < 20) {
|
||||||
|
fElastic = fCalc;
|
||||||
|
}
|
||||||
|
|
||||||
status = NXDputalias(pNexus->fileHandle, pNexus->dictHandle,alias,
|
status = NXDputalias(pNexus->fileHandle, pNexus->dictHandle,alias,
|
||||||
&fElastic);
|
&fElastic);
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
}
|
}
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
static int FMputTTH(SConnection *pCon, int argc, char *argv[]){
|
static int FMputTTH(SConnection *pCon, int argc, char *argv[]){
|
||||||
@ -909,6 +913,7 @@ static int FMcopyMergedSum(SConnection *pCon, int argc, char *argv[]){
|
|||||||
focusmerge putsum nxscriptmod bankname alias
|
focusmerge putsum nxscriptmod bankname alias
|
||||||
focusmerge putelastic nxscriptmod alias theoelastic
|
focusmerge putelastic nxscriptmod alias theoelastic
|
||||||
focusmerge toflambda
|
focusmerge toflambda
|
||||||
|
focusmerge elastic
|
||||||
|
|
||||||
nxscriptmod = name of the nxscript module used for writing, must be open
|
nxscriptmod = name of the nxscript module used for writing, must be open
|
||||||
alias = The alias under which to write the data item
|
alias = The alias under which to write the data item
|
||||||
@ -944,6 +949,11 @@ int FocusMergeAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
if(strcmp(argv[1],"toflambda") == 0){
|
if(strcmp(argv[1],"toflambda") == 0){
|
||||||
return TOFLambda(pSics, pCon,argc,argv);
|
return TOFLambda(pSics, pCon,argc,argv);
|
||||||
}
|
}
|
||||||
|
if(strcmp(argv[1],"elastic") == 0){
|
||||||
|
fElastic = calcElastic(pSics,pCon);
|
||||||
|
SCPrintf(pCon,eValue,"tofelastic = %f", fElastic);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if(strcmp(argv[1],"puttwotheta") == 0)
|
if(strcmp(argv[1],"puttwotheta") == 0)
|
||||||
{
|
{
|
||||||
|
3
ifile.c
3
ifile.c
@ -49,11 +49,12 @@
|
|||||||
|
|
||||||
static IPair *CreateNewEntry(char *name, char *val, IPair *pN)
|
static IPair *CreateNewEntry(char *name, char *val, IPair *pN)
|
||||||
{
|
{
|
||||||
IPair *pRes;
|
IPair *pRes = NULL;
|
||||||
|
|
||||||
pRes = (IPair *)malloc(sizeof(IPair));
|
pRes = (IPair *)malloc(sizeof(IPair));
|
||||||
if(!pRes)
|
if(!pRes)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
memset(pRes,0,sizeof(IPair));
|
||||||
if(name)
|
if(name)
|
||||||
pRes->name = strdup(name);
|
pRes->name = strdup(name);
|
||||||
if(val)
|
if(val)
|
||||||
|
4
make_gen
4
make_gen
@ -37,7 +37,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
|||||||
sicshdbadapter.o polldriv.o sicspoll.o statemon.o hmslave.o \
|
sicshdbadapter.o polldriv.o sicspoll.o statemon.o hmslave.o \
|
||||||
nwatch.o asyncqueue.o asyncprotocol.o sicsobj.o \
|
nwatch.o asyncqueue.o asyncprotocol.o sicsobj.o \
|
||||||
nxcopy.o nxinterhelper.o nxinter_wrap.o genericcontroller.o nxstack.o \
|
nxcopy.o nxinterhelper.o nxinter_wrap.o genericcontroller.o nxstack.o \
|
||||||
sctdriveadapter.o
|
sctdriveadapter.o sctdriveobj.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
|
||||||
@ -60,7 +60,7 @@ full: purge all
|
|||||||
SICServer: $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) \
|
SICServer: $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) \
|
||||||
$(VELOOBJ) $(DIFIL) $(EXTRA) \
|
$(VELOOBJ) $(DIFIL) $(EXTRA) \
|
||||||
$(SUBLIBS)
|
$(SUBLIBS)
|
||||||
$(CC) -g -o SICServer \
|
$(CC) -g -pg -o SICServer \
|
||||||
$(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) \
|
$(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) \
|
||||||
$(VELOOBJ) $(DIFOBJ) $(EXTRA) $(LIBS)
|
$(VELOOBJ) $(DIFOBJ) $(EXTRA) $(LIBS)
|
||||||
|
|
||||||
|
@ -312,7 +312,11 @@ int SctMakeDriveAdapter(SConnection *pCon, SicsInterp *pSics, void *object,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------*/
|
/*---------------------------------------------------------------*/
|
||||||
|
int SctMakeDriveObject(SConnection *pCon, SicsInterp *pSics, void *object,
|
||||||
|
int argc, char *argv[]);
|
||||||
|
|
||||||
void SctDriveInit(void) {
|
void SctDriveInit(void) {
|
||||||
AddCmd("makesctdrive", SctMakeDriveAdapter);
|
AddCmd("makesctdrive", SctMakeDriveAdapter);
|
||||||
AddCmd("dynsctdrive", SctMakeDriveAdapter);
|
AddCmd("dynsctdrive", SctMakeDriveAdapter);
|
||||||
|
AddCmd("makesctdriveobj",SctMakeDriveObject);
|
||||||
}
|
}
|
||||||
|
337
sctdriveobj.c
Normal file
337
sctdriveobj.c
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
/**
|
||||||
|
* This is a base class for any drivable object which uses the new
|
||||||
|
* scriptcontext to control the actual driving operation. This can also
|
||||||
|
* serve as a drivable adapter to nodes in other objects.
|
||||||
|
*
|
||||||
|
* copyright: see file COPYRIGHT
|
||||||
|
*
|
||||||
|
* Mark Koennecke, June-July 2008
|
||||||
|
*/
|
||||||
|
#include <sics.h>
|
||||||
|
#include <tcl.h>
|
||||||
|
#include <sicsobj.h>
|
||||||
|
#include <scriptcontext.h>
|
||||||
|
#include <sicshipadaba.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
pIDrivable pDriv;
|
||||||
|
SctController *c;
|
||||||
|
int doNotKillNode;
|
||||||
|
} DrivObjPriv, *pDrivObjPriv;
|
||||||
|
/*---------------------------------------------------------------*/
|
||||||
|
static void *SCTDRIVGetInterface(void *data, int iD){
|
||||||
|
pSICSOBJ self = NULL;
|
||||||
|
pDrivObjPriv pPriv;
|
||||||
|
|
||||||
|
self = (pSICSOBJ)data;
|
||||||
|
pPriv = (pDrivObjPriv)self->pPrivate;
|
||||||
|
if(self != NULL && pPriv != NULL && iD == DRIVEID){
|
||||||
|
if (self->objectNode == NULL) return NULL;
|
||||||
|
return pPriv->pDriv;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
This routine can return either OKOK or HWFault when thing
|
||||||
|
go wrong. However, the return value of Halt is usually ignored!
|
||||||
|
------------------------------------------------------------------*/
|
||||||
|
static int SCTDRIVHalt(void *data) {
|
||||||
|
pSICSOBJ self = NULL;
|
||||||
|
pDrivObjPriv pPriv;
|
||||||
|
char dummy[16];
|
||||||
|
|
||||||
|
self = (pSICSOBJ)data;
|
||||||
|
pPriv = (pDrivObjPriv)self->pPrivate;
|
||||||
|
if (GetHdbProperty(self->objectNode,"halt", dummy, sizeof dummy)) {
|
||||||
|
SctQueueNode(pPriv->c, self->objectNode, HaltPRIO, "halt", NULL);
|
||||||
|
} else if (GetHdbProperty(self->objectNode, "status", dummy, sizeof dummy)) {
|
||||||
|
SetHdbProperty(self->objectNode, "status", "idle");
|
||||||
|
}
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
This routine can return either 1 or 0. 1 means the position can
|
||||||
|
be reached, 0 NOT
|
||||||
|
If 0, error shall contain up to errlen characters of information
|
||||||
|
about which limit was violated
|
||||||
|
------------------------------------------------------------------*/
|
||||||
|
static int SCTDRIVCheckLimits(void *data, float val,
|
||||||
|
char *error, int errlen){
|
||||||
|
pSICSOBJ self = NULL;
|
||||||
|
pDrivObjPriv pPriv;
|
||||||
|
char script[1024];
|
||||||
|
int status;
|
||||||
|
Tcl_Interp *pTcl = NULL;
|
||||||
|
char *result;
|
||||||
|
|
||||||
|
self = (pSICSOBJ)data;
|
||||||
|
pPriv = (pDrivObjPriv)self->pPrivate;
|
||||||
|
snprintf(script,1024,"%f", val);
|
||||||
|
SetHdbProperty(self->objectNode,"target", script);
|
||||||
|
if(GetHdbProperty(self->objectNode,"checklimits",script,1024)){
|
||||||
|
status = SctCallInContext(pServ->dummyCon, script,
|
||||||
|
self->objectNode, pPriv->c, &result);
|
||||||
|
if(SctVerbose(pPriv->c)){
|
||||||
|
SCPrintf(pServ->dummyCon, eWarning, "script %s called with result %s\n ",
|
||||||
|
script, result);
|
||||||
|
}
|
||||||
|
if(status == 0){
|
||||||
|
strncpy(error,result,errlen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
This routine can return 0 when a limit problem occurred
|
||||||
|
OKOK when the motor was successfully started
|
||||||
|
HWFault when a problem occured starting the device
|
||||||
|
Possible errors shall be printed to pCon
|
||||||
|
For real motors, this is supposed to try at least three times
|
||||||
|
to start the motor in question
|
||||||
|
val is the value to drive the motor too
|
||||||
|
------------------------------------------------------------------*/
|
||||||
|
static long SCTDRIVSetValue(void *data, SConnection *pCon, float val){
|
||||||
|
pSICSOBJ self = NULL;
|
||||||
|
pDrivObjPriv pPriv;
|
||||||
|
int status;
|
||||||
|
hdbValue v;
|
||||||
|
|
||||||
|
self = (pSICSOBJ)data;
|
||||||
|
pPriv = (pDrivObjPriv)self->pPrivate;
|
||||||
|
|
||||||
|
v.dataType = HIPFLOAT;
|
||||||
|
v.v.doubleValue = (double)val;
|
||||||
|
SetHdbProperty(self->objectNode,"writestatus", "start");
|
||||||
|
status = SetHipadabaPar(self->objectNode, v, pCon);
|
||||||
|
if(status == 1){
|
||||||
|
return OKOK;
|
||||||
|
} else {
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
Checks the status of a running motor. Possible return values
|
||||||
|
HWBusy The motor is still running
|
||||||
|
OKOK or HWIdle when the motor finished driving
|
||||||
|
HWFault when a hardware problem ocurred
|
||||||
|
HWPosFault when the hardware cannot reach a position
|
||||||
|
Errors are duly to be printed to pCon
|
||||||
|
For real motors CheckStatus again shall try hard to fix any
|
||||||
|
issues with the motor
|
||||||
|
------------------------------------------------------------------*/
|
||||||
|
static int SCTDRIVCheckStatus(void *data, SConnection *pCon){
|
||||||
|
pSICSOBJ self = NULL;
|
||||||
|
pDrivObjPriv pPriv;
|
||||||
|
char script[1024];
|
||||||
|
int status;
|
||||||
|
Tcl_Interp *pTcl = NULL;
|
||||||
|
char *result;
|
||||||
|
SConnection *con;
|
||||||
|
|
||||||
|
self = (pSICSOBJ)data;
|
||||||
|
pPriv = (pDrivObjPriv)self->pPrivate;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check if the write command has gone through
|
||||||
|
*/
|
||||||
|
if(GetHdbProperty(self->objectNode,"writestatus", script,1024)){
|
||||||
|
if(strcmp(script,"start") == 0){
|
||||||
|
return HWBusy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* run the checkstatus script
|
||||||
|
*/
|
||||||
|
if(!GetHdbProperty(self->objectNode,"checkstatus",script,1024)){
|
||||||
|
if (!GetHdbProperty(self->objectNode,"status",script,1024)){
|
||||||
|
SCWrite(pCon,
|
||||||
|
"ERROR: configuration problem: no checkstatus script!", eError);
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
result = script;
|
||||||
|
} else {
|
||||||
|
status = SctCallInContext(pCon,script, self->objectNode,
|
||||||
|
pPriv->c, &result);
|
||||||
|
if (status == 0) {
|
||||||
|
SCPrintf(pCon,eError," script %s returned %s",
|
||||||
|
script, result);
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
if(SctVerbose(pPriv->c)){
|
||||||
|
SCPrintf(pCon,eError," script %s returned %s",
|
||||||
|
script, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
GetValue is supposed to read a motor position
|
||||||
|
On errors, -99999999.99 is returned and messages printed to pCon
|
||||||
|
------------------------------------------------------------------*/
|
||||||
|
static float SCTDRIVGetValue(void *data, SConnection *pCon){
|
||||||
|
pSICSOBJ self = NULL;
|
||||||
|
pDrivObjPriv pPriv;
|
||||||
|
float val = -99999999.99;
|
||||||
|
int status;
|
||||||
|
char error[256];
|
||||||
|
hdbValue v;
|
||||||
|
|
||||||
|
self = (pSICSOBJ)data;
|
||||||
|
pPriv = (pDrivObjPriv)self->pPrivate;
|
||||||
|
if(GetHdbProperty(self->objectNode,"geterror", error, 256)){
|
||||||
|
SCWrite(pCon,error, eError);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
return (float)self->objectNode->value.v.doubleValue;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------*/
|
||||||
|
void AssignSctDrive(pIDrivable pDriv){
|
||||||
|
pDriv->Halt = SCTDRIVHalt;
|
||||||
|
pDriv->CheckLimits = SCTDRIVCheckLimits;
|
||||||
|
pDriv->SetValue = SCTDRIVSetValue;
|
||||||
|
pDriv->CheckStatus = SCTDRIVCheckStatus;
|
||||||
|
pDriv->GetValue = SCTDRIVGetValue;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void KillDriveOBJ(void *data){
|
||||||
|
pSICSOBJ self = (pSICSOBJ)data;
|
||||||
|
pDrivObjPriv pPriv;
|
||||||
|
|
||||||
|
if(self == NULL){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(self->KillPrivate != NULL && self->pPrivate != NULL){
|
||||||
|
self->KillPrivate(self->pPrivate);
|
||||||
|
}
|
||||||
|
RemoveHdbNodeFromParent(self->objectNode, pServ->dummyCon);
|
||||||
|
free(self);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
pSICSOBJ MakeSctDriveObj(pHdb node, char *class, SctController *c){
|
||||||
|
pSICSOBJ pNew = NULL;
|
||||||
|
pDrivObjPriv pPriv = NULL;
|
||||||
|
hdbValue val;
|
||||||
|
|
||||||
|
pNew = (pSICSOBJ)malloc(sizeof(SICSOBJ));
|
||||||
|
pPriv = (pDrivObjPriv)malloc(sizeof(DrivObjPriv));
|
||||||
|
if(pNew == NULL || pPriv == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(pNew,0,sizeof(SICSOBJ));
|
||||||
|
memset(pPriv,0,sizeof(DrivObjPriv));
|
||||||
|
|
||||||
|
pNew->pDes = CreateDescriptor(class);
|
||||||
|
pPriv->pDriv = CreateDrivableInterface();
|
||||||
|
if(pNew->pDes == NULL || pPriv->pDriv == NULL){
|
||||||
|
free(pNew);
|
||||||
|
free(pPriv);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
pNew->objectNode = node;
|
||||||
|
AssignSctDrive(pPriv->pDriv);
|
||||||
|
pPriv->c = c;
|
||||||
|
pNew->pDes->parNode = pNew->objectNode;
|
||||||
|
pNew->pDes->GetInterface = SCTDRIVGetInterface;
|
||||||
|
pNew->pPrivate = pPriv;
|
||||||
|
pNew->KillPrivate = DefaultKill;
|
||||||
|
return pNew;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------
|
||||||
|
* This actually has two syntaxes:
|
||||||
|
* makesctdrive name path-to-existing-node class SctController
|
||||||
|
* makesctdrive name type priv class SctController
|
||||||
|
*--------------------------------------------------------------------------*/
|
||||||
|
int SctMakeDriveObject(SConnection *pCon, SicsInterp *pSics, void *object,
|
||||||
|
int argc, char *argv[]) {
|
||||||
|
pHdb node = NULL;
|
||||||
|
pDrivObjPriv pPriv = NULL;
|
||||||
|
pSICSOBJ pNew = NULL;
|
||||||
|
pSICSOBJ pSct = NULL;
|
||||||
|
SctController *c = NULL;
|
||||||
|
int priv, type, status;
|
||||||
|
hdbValue val;
|
||||||
|
|
||||||
|
if(argc < 5){
|
||||||
|
SCWrite(pCon,"ERROR: not enough arguments to SctMakeDriveObject", eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
c = (SctController *)pSct->pPrivate;
|
||||||
|
pNew = MakeSctDriveObj(node,argv[3],c);
|
||||||
|
pPriv = (pDrivObjPriv)pNew->pPrivate;
|
||||||
|
pPriv->doNotKillNode = 1; /* the node is owned by someone else*/
|
||||||
|
} else {
|
||||||
|
/* 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(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);
|
||||||
|
}
|
||||||
|
if(pNew == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: failed to create drive object", eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
status = AddCommand(pSics,
|
||||||
|
argv[1],
|
||||||
|
InterInvokeSICSOBJ,
|
||||||
|
KillDriveOBJ,
|
||||||
|
pNew);
|
||||||
|
if(status != 1){
|
||||||
|
KillSICSOBJ(pNew);
|
||||||
|
SCPrintf(pCon,eError,"ERROR: failed create duplicate command %s", argv[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
35
sicsobj.c
35
sicsobj.c
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
extern int decodeSICSPriv(char *txt); /* from access.c */
|
extern int decodeSICSPriv(char *txt); /* from access.c */
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
static void DefaultKill(void *data){
|
void DefaultKill(void *data){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
@ -209,22 +209,47 @@ static int MakeScriptFunc(pSICSOBJ self, SConnection *pCon,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static int isNodePrintable(pHdb node){
|
||||||
|
switch(node->value.dataType){
|
||||||
|
case HIPNONE:
|
||||||
|
case HIPFUNC:
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
int InvokeSICSOBJ(SConnection *pCon, SicsInterp *pSics, void *pData,
|
int InvokeSICSOBJ(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[]){
|
int argc, char *argv[]){
|
||||||
pSICSOBJ self = NULL;
|
pSICSOBJ self = NULL;
|
||||||
int status;
|
int status;
|
||||||
pHdb parNode;
|
pHdb parNode;
|
||||||
char buffer[132];
|
char buffer[132];
|
||||||
|
hdbValue data;
|
||||||
|
pDynString parData;
|
||||||
|
|
||||||
self = (pSICSOBJ)pData;
|
self = (pSICSOBJ)pData;
|
||||||
assert(self != NULL);
|
assert(self != NULL);
|
||||||
|
|
||||||
if(argc < 2){
|
|
||||||
SCWrite(pCon,"ERROR: Nothing to process",eError);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
parNode = self->objectNode;
|
parNode = self->objectNode;
|
||||||
|
if(parNode != NULL && isNodePrintable(parNode) ){
|
||||||
|
status = GetHipadabaPar(parNode,&data,pCon);
|
||||||
|
if(status != 1){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
parData = formatValue(data, parNode);
|
||||||
|
if(parData == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: failed to format data", eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
SCPrintf(pCon,eValue,"%s = %s", argv[0], GetCharArray(parData));
|
||||||
|
DeleteDynString(parData);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
SCWrite(pCon,"ERROR: nothing to print", eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
parNode = GetHipadabaNode(self->objectNode,argv[1]);
|
parNode = GetHipadabaNode(self->objectNode,argv[1]);
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,9 @@ typedef int (*SICSOBJFunc)(pSICSOBJ self, SConnection *pCon,
|
|||||||
pSICSOBJ MakeSICSOBJ(char *name, char *class);
|
pSICSOBJ MakeSICSOBJ(char *name, char *class);
|
||||||
pSICSOBJ MakeSICSOBJv(char *name, char *class, int type, int priv);
|
pSICSOBJ MakeSICSOBJv(char *name, char *class, int type, int priv);
|
||||||
void KillSICSOBJ(void *data);
|
void KillSICSOBJ(void *data);
|
||||||
|
void DefaultKill(void *data);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This creates a new SICS object and installs it in the interpreter. It returns
|
* This creates a new SICS object and installs it in the interpreter. It returns
|
||||||
* the newly created SICS object such that the caller can continue
|
* the newly created SICS object such that the caller can continue
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#DFORTIFY= -DFORTIFY
|
#DFORTIFY= -DFORTIFY
|
||||||
#FORTIFYOBJ= fortify.o strdup.o
|
#FORTIFYOBJ= fortify.o strdup.o
|
||||||
#DFORTIFY= -p
|
DFORTIFY= -pg
|
||||||
|
|
||||||
MFLAGS=-f makefile_linux$(DUMMY)
|
MFLAGS=-f makefile_linux$(DUMMY)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user