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

370 lines
10 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
* managment 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"
/*==========================================================================*/
typedef struct __STATEMON {
pObjectDescriptor pDes;
pICallBack pCall;
} StateMon;
/*============================ Callbacks =================================*/
static int DevexecCallback(int iEvent, void *text, void *pData)
{
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)
{
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)
{
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)
{
SConnection *pCon = (SConnection *) pUser;
char *device = (char *) pEvent;
char buffer[256];
if (pCon == NULL || !SCisConnected(pCon)) {
return -1;
}
if (pCon == NULL || device == NULL) {
printf("Bad StateInterest in statemon\n");
return 0;
}
if (iEvent == STSTART) {
snprintf(buffer, 255, "STARTED = %s", device);
SCWrite(pCon, buffer, eWarning);
}
if (iEvent == STEND) {
snprintf(buffer, 255, "FINISH = %s", device);
SCWrite(pCon, buffer, eWarning);
}
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)
{
SConnection *pCon = (SConnection *) pUser;
char *device = (char *) pEvent, *path = NULL;
char buffer[1024];
pHdb node = NULL;
if (pCon == NULL || !SCisConnected(pCon)) {
return -1;
}
if (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);
SCWrite(pCon, buffer, eWarning);
}
if (iEvent == STEND) {
snprintf(buffer, 1024, "%s FINISH", path);
SCWrite(pCon, buffer, eWarning);
}
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);
}
free(self);
}
}
/*---------------------------------------------------------------------------*/
int StateMonFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pStateMon pNew = NULL;
commandContext cc;
pICallBack target = NULL;
void *pPtr = NULL, *exe = NULL, *pDevexec = 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();
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, DRIVSTAT, DevexecCallback, pNew, NULL);
target = GetCallbackInterface(exe);
assert(target != NULL);
RegisterCallback(target, BATCHSTART, ExeCallback, pNew, NULL);
RegisterCallback(target, BATCHEND, ExeCallback, pNew, NULL);
if (argc > 1) {
pPtr = FindCommandData(pSics, argv[1], "ScanObject");
if (pPtr == NULL) {
SCWrite(pCon, "ERROR: failked to locate scan object", eError);
} else {
target = GetCallbackInterface(pPtr);
assert(target != NULL);
RegisterCallback(target, SCANSTART, StateMonScanInterest, pNew,
NULL);
RegisterCallback(target, SCANEND, StateMonScanInterest, pNew, NULL);
}
}
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;
SConnection *callCon = 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) {
callCon = SCCopyConnection(pCon);
if (callCon == NULL) {
SCWrite(pCon, "ERROR: out of memory registering interest", eError);
return 0;
}
lID = RegisterCallback(self->pCall, STSTART, StateInterest,
callCon, SCDeleteConnection);
SCRegister(pCon, pSics, self->pCall, lID);
lID = RegisterCallback(self->pCall, STEND, StateInterest,
callCon, 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);
}
}
SCSendOK(pCon);
return 1;
} else if (strcmp(argv[1], "hdbinterest") == 0) {
callCon = SCCopyConnection(pCon);
if (callCon == NULL) {
SCWrite(pCon, "ERROR: out of memory registering interest", eError);
return 0;
}
lID = RegisterCallback(self->pCall, STSTART, StateHdbInterest,
callCon, SCDeleteConnection);
lID = RegisterCallback(self->pCall, STEND, StateHdbInterest,
callCon, NULL);
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;
}
SCWrite(pCon, "ERROR: keyword not recognized", eError);
return 0;
}