Files
sics/statemon.c
Ferdi Franceschini 3a3b6764ee SICS-377 hipadaba_configuration_common.tcl
One typo and forgetting to clear a temporary variable meant that the list of candidates for removal never shrank while pruning

reflectometer/config/motors/sct_batmotor.tcl
The beam attenuator is on axis D not A.  Also provide statemon feedback, "busy" or "idle"

sans/config/velsel/velsel.tcl
Update velocity selector parameters for NVS 43

SICS-374 sans/config/velsel/sct_velsel.tcl
Set velocity selector identifier

script_context_util.tcl
Don't override the "klass' attribute, just make sure that it matches the hdb klass property if it's defined.

event.h and statemon.c
Added statemon BUSY and IDLE events for the scbat because it when it oscillates it's busy doing something.

r2875 | ffr | 2010-01-22 20:41:36 +1100 (Fri, 22 Jan 2010) | 18 lines
2012-11-15 16:59:48 +11:00

436 lines
14 KiB
C

/**
* This is a state monitor. It collects all the start and stop messages
* from the device executor and from scan and batch commands. Clients can
* listen to this in order to figure out what is actually going on in a
* given SICS installation. This might in the end supersede the status code
* management in status.c
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, January 2007
*/
#include <sics.h>
#include "exeman.h"
#include "scan.h"
#include "scan.i"
#include "stptok.h"
#include "statemon.h"
#include "sicshipadaba.h"
#include "sicsvar.h"
#define SICS_SUID "sics_suid"
pICallBack statemon_cbinterface = NULL;
/*==========================================================================*/
typedef struct __STATEMON {
pObjectDescriptor pDes;
pICallBack pCall;
}StateMon;
SConnection *pStateMonDummyCon = NULL;
/*============================ Callbacks =================================*/
static int DevexecCallback(int iEvent, void *text, void *pData,
commandContext cc){
char pDevice[132];
int eventCode;
pStateMon self = (pStateMon)pData;
memset(pDevice,0,132);
if(iEvent == DRIVSTAT){
stptok(text,pDevice,131," ");
if(strstr(text,"started") != NULL){
eventCode = STSTART;
} else if(strstr(text,"finished") != NULL) {
eventCode = STEND;
} else {
printf("Unrecognized event text from devexec in statemon.c: %s\n",
(char *)text);
return 0;
}
if(self != NULL){
InvokeCallBack(self->pCall,eventCode,pDevice);
}
}
return 1;
}
/*---------------------------------------------------------------------------*/
static int StateMonScanInterest(int iEvent, void *pEventData, void *pUser,
commandContext cc){
pScanData pScan = NULL;
pStateMon self = (pStateMon)pUser;
pScan = (pScanData)pEventData;
if(pScan == NULL || self == NULL){
printf("Bad StateMonScanInterst in statemon\n");
return 0;
}
if(iEvent == SCANSTART){
InvokeCallBack(self->pCall,STSTART,pScan->objectName);
return 1;
}else if(iEvent == SCANEND){
InvokeCallBack(self->pCall,STEND,pScan->objectName);
return 1;
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int ExeCallback(int iEvent, void *pEvent, void *pUser,
commandContext cc){
pStateMon self = (pStateMon)pUser;
char *name = (char *)pEvent;
char pBueffel[131];
if(self == NULL || name == NULL){
printf("Bad ExeCallback in statemon\n");
return 0;
}
if(iEvent == BATCHSTART){
snprintf(pBueffel,131,"exe %s",name);
InvokeCallBack(self->pCall,STSTART,pBueffel);
return 1;
}
if(iEvent == BATCHEND){
snprintf(pBueffel,131,"exe %s",name);
InvokeCallBack(self->pCall,STEND,pBueffel);
return 1;
}
return 0;
}
/*=============== user callbacks ============================================*/
static int StateInterest(int iEvent, void *pEvent, void *pUser,
commandContext cc){
SConnection *pCon = (SConnection *)pUser;
char *device = (char *)pEvent;
char buffer[256];
pSicsVariable pVar = NULL;
if( pCon == NULL || device == NULL) {
printf("Bad StateInterest in statemon\n");
return 0;
} else if (pCon == pStateMonDummyCon) {
if(iEvent == STSTART){
snprintf(buffer,255,"SUID MSG STARTED = %s", device);
SCWrite(pStateMonDummyCon,buffer,eError);
}
if(iEvent == STEND){
snprintf(buffer,255,"SUID MSG FINISH = %s", device);
SCWrite(pStateMonDummyCon,buffer,eError);
}
pVar = (pSicsVariable)FindCommandData(pServ->pSics,SICS_SUID,"SicsVariable");
if (pVar == NULL) {
SCWrite(pStateMonDummyCon,"ERROR: StateMon.c: Could not find SUID SicsVariable",eError);
return 0;
}
(pVar->iVal)++;
InvokeCallBack(pVar->pCall, VALUECHANGE, pVar);
} else {
if(iEvent == STSTART){
snprintf(buffer,255,"STARTED = %s", device);
SCWriteInContext(pCon,buffer,eWarning,cc);
}
if(iEvent == STEND){
snprintf(buffer,255,"FINISH = %s", device);
SCWriteInContext(pCon,buffer,eWarning,cc);
}
if(iEvent == STPAUSE){
snprintf(buffer,255,"PAUSE = %s", device);
SCWriteInContext(pCon,buffer,eWarning,cc);
}
if(iEvent == STCONTINUE){
snprintf(buffer,255,"CONTINUE = %s", device);
SCWriteInContext(pCon,buffer,eWarning,cc);
}
if(iEvent == STBUSY){
snprintf(buffer,255,"BUSY = %s", device);
SCWriteInContext(pCon,buffer,eWarning,cc);
}
if(iEvent == STIDLE){
snprintf(buffer,255,"IDLE = %s", device);
SCWriteInContext(pCon,buffer,eWarning,cc);
}
}
return 1;
}
/*--------------------------------------------------------------------------*/
static pHdb recurseInterestNode(pHdb current, char *pDevice){
char pSicsdev[131], pAlias[132];
pHdb result = NULL;
char *alias = NULL, *pPtr = NULL;
memset(pSicsdev,0,132);
memset(pAlias,0,132);
if(current != NULL){
if(GetHdbProperty(current,"sicsdev",pSicsdev,131) != 0){
strtolower(pSicsdev);
if(strcmp(pSicsdev,pDevice) == 0){
return current;
}
/*
* try to look for aliases, too
*/
alias = FindAliases(pServ->pSics,pSicsdev);
pPtr = alias;
if(pPtr != NULL){
while((pPtr = stptok(pPtr,pAlias,131,",")) != NULL){
if(strcmp(pAlias,pDevice) == 0){
return current;
}
}
if(alias != NULL){
free(alias);
}
}
}
current = current->child;
while(current != NULL){
result = recurseInterestNode(current, pDevice);
if(result != NULL){
return result;
}
current = current->next;
}
}
return NULL;
}
/*--------------------------------------------------------------------------*/
static pHdb locateInterestNode(char *device){
char pDevice[132], pSicsdev[132];
pHdb current = NULL, result = NULL;
memset(pDevice,0,132);
memset(pSicsdev,0,132);
/*
* this is to strip off exes batch file name
*/
stptok(device,pDevice,131," ");
strtolower(pDevice);
current = GetHipadabaRoot();
return recurseInterestNode(current,pDevice);
}
/*--------------------------------------------------------------------------*/
static int StateHdbInterest(int iEvent, void *pEvent, void *pUser,
commandContext cc){
SConnection *pCon = (SConnection *)pUser;
char *device = (char *)pEvent, *path = NULL;
char buffer[1024];
pHdb node = NULL;
if(pCon == NULL || device == NULL){
printf("Bad StateHdbInterest in statemon\n");
return 0;
}
node = locateInterestNode(device);
if(node != NULL){
path = GetHipadabaPath(node);
if(iEvent == STSTART){
snprintf(buffer,1024,"%s STARTED", path);
SCWriteInContext(pCon,buffer,eWarning,cc);
}
if(iEvent == STEND){
snprintf(buffer,1024,"%s FINISH", path);
SCWriteInContext(pCon,buffer,eWarning,cc);
}
if(path != NULL){
free(path);
}
}
return 1;
}
/*====================== interpreter interface ==============================*/
static void killStateMon(void *pData){
pStateMon self = NULL;
self = (pStateMon)pData;
if(self != NULL){
if(self->pDes != NULL){
DeleteDescriptor(self->pDes);
}
if(self->pCall != NULL){
DeleteCallBackInterface(self->pCall);
}
if(pStateMonDummyCon != NULL) {
SCDeleteConnection(pStateMonDummyCon);
}
free(self);
}
}
/*---------------------------------------------------------------------------*/
int StateMonFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]){
long lID;
pStateMon pNew = NULL;
commandContext cc;
pICallBack target = NULL;
void *pPtr = NULL, *exe = NULL, *pDevexec = NULL;
pSicsVariable pRes = NULL;
exe = FindCommandData(pSics,"exe", "ExeManager");
pDevexec = FindCommandData(pSics,"stopexe","DeviceExecutor");
if(exe == NULL || pDevexec == NULL){
SCWrite(pCon,
"ERROR: both the device executor and the batch file module must be installed before initialising statemon",
eError);
return 0;
}
/*
* generate data structures
*/
strcpy(cc.deviceID,"statemon");
cc.transID = -120;
pNew = (pStateMon)malloc(sizeof(StateMon));
if(pNew == NULL){
SCWrite(pCon,"ERROR: out of memory creating StateMon",eError);
return 0;
}
memset(pNew,0,sizeof(StateMon));
pNew->pDes = CreateDescriptor("statemon");
pNew->pCall = CreateCallBackInterface();
statemon_cbinterface = pNew->pCall;
if(pNew->pDes == NULL || pNew->pCall == NULL){
SCWrite(pCon,"ERROR: out of memory creating StateMon",eError);
return 0;
}
/*
* register callbacks
*/
target = GetCallbackInterface(pDevexec);
assert(target != NULL);
RegisterCallback(target,cc,DRIVSTAT,DevexecCallback,pNew,NULL);
target = GetCallbackInterface(exe);
assert(target != NULL);
RegisterCallback(target,cc,BATCHSTART,ExeCallback,pNew,NULL);
RegisterCallback(target,cc,BATCHEND,ExeCallback,pNew,NULL);
if(argc > 1) {
pPtr = FindCommandData(pSics,argv[1],"ScanObject");
if(pPtr == NULL){
SCWrite(pCon,"ERROR: failed to locate scan object",eError);
} else {
target = GetCallbackInterface(pPtr);
assert(target != NULL);
RegisterCallback(target,cc,SCANSTART,StateMonScanInterest,pNew,NULL);
RegisterCallback(target,cc,SCANEND,StateMonScanInterest,pNew,NULL);
}
}
/* Make dummy connection for SUID (instrument state id) */
pStateMonDummyCon = SCCreateDummyConnection(pSics);
lID = RegisterCallback(pNew->pCall, SCGetContext(pStateMonDummyCon),STSTART, StateInterest, pStateMonDummyCon, NULL);
SCRegister(pStateMonDummyCon,pSics, pNew->pCall,lID);
lID = RegisterCallback(pNew->pCall, SCGetContext(pStateMonDummyCon),STEND, StateInterest, pStateMonDummyCon, NULL);
SCRegister(pStateMonDummyCon,pSics, pNew->pCall,lID);
pRes = VarCreate(usInternal,veInt,SICS_SUID);
AddCommand(pSics,SICS_SUID,VarWrapper,(KillFunc)VarKill,pRes);
/*
* TODO: add kill functions
*/
AddCommand(pSics,"statemon",StateMonAction,killStateMon,pNew);
return 1;
}
/*---------------------------------------------------------------------------*/
int StateMonAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]){
long lID;
int i;
pStateMon self = NULL;
self = (pStateMon)pData;
assert(self != NULL);
if(argc < 2){
SCWrite(pCon,"ERROR: not enough arguments to statemon",eError);
return 0;
}
strtolower(argv[1]);
if(strcmp(argv[1],"interest") == 0){
lID = RegisterCallback(self->pCall, SCGetContext(pCon),STSTART, StateInterest,
pCon, NULL);
SCRegister(pCon,pSics, self->pCall,lID);
lID = RegisterCallback(self->pCall, SCGetContext(pCon),STEND, StateInterest,
pCon, NULL);
SCRegister(pCon,pSics, self->pCall,lID);
lID = RegisterCallback(self->pCall, SCGetContext(pCon),STPAUSE, StateInterest,
pCon, NULL);
SCRegister(pCon,pSics, self->pCall,lID);
lID = RegisterCallback(self->pCall, SCGetContext(pCon),STCONTINUE, StateInterest,
pCon, NULL);
SCRegister(pCon,pSics, self->pCall,lID);
lID = RegisterCallback(self->pCall, SCGetContext(pCon),STBUSY, StateInterest,
pCon, NULL);
SCRegister(pCon,pSics, self->pCall,lID);
lID = RegisterCallback(self->pCall, SCGetContext(pCon),STIDLE, StateInterest,
pCon, NULL);
SCRegister(pCon,pSics, self->pCall,lID);
SCSendOK(pCon);
return 1;
} else if(strcmp(argv[1],"uninterest") == 0) {
for(i = 0; i < 2; i++){
lID = SCgetCallbackID(pCon,self->pCall);
if(lID >= 0){
RemoveCallback(self->pCall,lID);
SCUnregisterID(pCon,lID);
}
}
SCSendOK(pCon);
return 1;
} else if(strcmp(argv[1],"hdbinterest") == 0){
lID = RegisterCallback(self->pCall, SCGetContext(pCon),STSTART, StateHdbInterest,
pCon, NULL);
SCRegister(pCon,pSics, self->pCall,lID);
lID = RegisterCallback(self->pCall, SCGetContext(pCon),STEND, StateHdbInterest,
pCon, NULL);
SCRegister(pCon,pSics, self->pCall,lID);
SCSendOK(pCon);
return 1;
} else if(strcmp(argv[1],"start") == 0) {
if(argc > 2){
InvokeCallBack(self->pCall,STSTART,argv[2]);
SCSendOK(pCon);
return 1;
}
return 0;
} else if(strcmp(argv[1],"stop") == 0) {
if(argc > 2){
InvokeCallBack(self->pCall,STEND,argv[2]);
SCSendOK(pCon);
return 1;
}
return 0;
} else if(strcmp(argv[1],"pause") == 0) {
if(argc > 2){
InvokeCallBack(self->pCall,STPAUSE,argv[2]);
SCSendOK(pCon);
return 1;
}
return 0;
} else if(strcmp(argv[1],"continue") == 0) {
if(argc > 2){
InvokeCallBack(self->pCall,STCONTINUE,argv[2]);
SCSendOK(pCon);
return 1;
}
return 0;
} else if(strcmp(argv[1],"busy") == 0) {
if(argc > 2){
InvokeCallBack(self->pCall,STBUSY,argv[2]);
SCSendOK(pCon);
return 1;
}
return 0;
} else if(strcmp(argv[1],"idle") == 0) {
if(argc > 2){
InvokeCallBack(self->pCall,STIDLE,argv[2]);
SCSendOK(pCon);
return 1;
}
return 0;
}
SCWrite(pCon,"ERROR: keyword not recognized",eError);
return 0;
}