999 lines
26 KiB
C
999 lines
26 KiB
C
/*
|
|
* Experience has shown that integrating existing SICS objects into the
|
|
* Hierarchical Parameter Database (Hdb) is a difficult task without reworking
|
|
* the complete SICS object model. Rather, it seems easier to adapt some
|
|
* critical objects to the Hdb with some glue code. Following the facade or
|
|
* adapter design pattern. This is the purpose of this module. For the moment
|
|
* the external interface is only an interpreter function which will be used to
|
|
* install suitable SICS objects into the Hdb tree and generates the necessary
|
|
* adapters internally. This code can be used to adapt to:
|
|
* - motors
|
|
* - the data segment of histogram memories
|
|
*
|
|
* copyright: see file COPYRIGHT
|
|
*
|
|
* Mark Koennecke, November 2006
|
|
*/
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <sics.h>
|
|
#include "stptok.h"
|
|
#include "motor.h"
|
|
#include "HistMem.h"
|
|
#include "HistMem.i"
|
|
#include "HistDriv.i"
|
|
#include "sicsvar.h"
|
|
#include "counter.h"
|
|
#include "lld.h"
|
|
#include "sicshipadaba.h"
|
|
#include "sicshdbadapter.h"
|
|
#include "sicsdata.h"
|
|
#include "HistMem.i"
|
|
|
|
#define PRIVNAM "priv"
|
|
/*==================== support code ====================================*/
|
|
static void AddPrivProperty(pHdb node, int priv)
|
|
{
|
|
char pPriv[80];
|
|
switch (priv) {
|
|
case usInternal:
|
|
strcpy(pPriv, "internal");
|
|
break;
|
|
case usMugger:
|
|
strcpy(pPriv, "manager");
|
|
break;
|
|
case usUser:
|
|
strcpy(pPriv, "user");
|
|
break;
|
|
case usSpy:
|
|
strcpy(pPriv, "spy");
|
|
break;
|
|
default:
|
|
assert(0);
|
|
break;
|
|
}
|
|
SetHdbProperty(node, PRIVNAM, pPriv);
|
|
}
|
|
|
|
/*=================== motor code =======================================*/
|
|
static int MoveCallback(int iEvent, void *eventData, void *userData)
|
|
{
|
|
MotCallback *motData = (MotCallback *) eventData;
|
|
pHdb motor = (pHdb) userData;
|
|
pHdb pos = NULL;
|
|
|
|
if (iEvent == MOTDRIVE && motData != NULL && motor != NULL) {
|
|
UpdateHipadabaPar(motor, MakeHdbFloat((double) motData->fVal)
|
|
, NULL);
|
|
pos = GetHipadabaNode(motor, "position");
|
|
if (pos != NULL) {
|
|
UpdateHipadabaPar(pos, MakeHdbFloat((double) motData->fVal)
|
|
, NULL);
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------*/
|
|
static int MotorValueCallback(int iEvent, void *eventData, void *userData)
|
|
{
|
|
pHdb motor = (pHdb) userData;
|
|
pMotor pMot = (pMotor) eventData;
|
|
pHdb current = NULL;
|
|
float fVal;
|
|
|
|
/*
|
|
* as setting some motor parameters might cause other motor
|
|
* parametes to change too, I opt for the cheap solution to check
|
|
* them all.
|
|
*/
|
|
if (iEvent == HDBVAL && motor != NULL && pMot != NULL) {
|
|
current = motor->child;
|
|
while (current != NULL) {
|
|
MotorGetPar(pMot, current->name, &fVal);
|
|
if (fVal != current->value.v.doubleValue) {
|
|
UpdateHipadabaPar(current, MakeHdbFloat((double) fVal), NULL);
|
|
}
|
|
current = current->next;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------*/
|
|
static hdbCallbackReturn MotorParSetCallback(pHdb currentNode,
|
|
void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
pMotor pMot = (pMotor) userData;
|
|
SConnection *pCon = NULL;
|
|
int status;
|
|
pHdbDataMessage mm = NULL;
|
|
|
|
if ((mm = GetHdbSetMessage(message)) == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
pCon = mm->callData;
|
|
|
|
assert(pMot != NULL && pCon != NULL);
|
|
status = MotorSetPar(pMot, pCon, currentNode->name,
|
|
(float) mm->v->v.doubleValue);
|
|
if (status == 1) {
|
|
return hdbContinue;
|
|
} else {
|
|
return hdbAbort;
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
static hdbCallbackReturn MotorParGetCallback(pHdb currentNode,
|
|
void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
pMotor pMot = (pMotor) userData;
|
|
float fVal;
|
|
int status;
|
|
pHdbDataMessage mm = NULL;
|
|
|
|
if ((mm = GetHdbGetMessage(message)) == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
|
|
assert(pMot != NULL);
|
|
status = MotorGetPar(pMot, currentNode->name, &fVal);
|
|
currentNode->value.v.doubleValue = fVal;
|
|
if (status == 1) {
|
|
return hdbContinue;
|
|
} else {
|
|
return hdbAbort;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------*/
|
|
static pHdb MakeMotParNode(char *name, pMotor pMot)
|
|
{
|
|
pHdb node = NULL;
|
|
pHdbCallback pCall = NULL;
|
|
char command[1024];
|
|
|
|
node = MakeHipadabaNode(name, HIPFLOAT, 1);
|
|
if (node != NULL) {
|
|
pCall = MakeHipadabaCallback(MotorParSetCallback, pMot, NULL);
|
|
if (pCall == NULL) {
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(node, pCall);
|
|
pCall = MakeHipadabaCallback(MotorParGetCallback, pMot, NULL);
|
|
if (pCall == NULL) {
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(node, pCall);
|
|
snprintf(command, 1023, "%s %s ", pMot->name, name);
|
|
SetHdbProperty(node, "sicscommand", command);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------*/
|
|
static int AddStdMotorPar(pHdb motorNode, pMotor pMot)
|
|
{
|
|
int i;
|
|
pHdb parNode = NULL;
|
|
char *addPar[] = { "target",
|
|
"hardlowerlim",
|
|
"hardupperlim",
|
|
NULL
|
|
};
|
|
|
|
i = 0;
|
|
while (addPar[i] != NULL) {
|
|
parNode = MakeMotParNode(addPar[i], pMot);
|
|
SetHdbProperty(parNode, PRIVNAM, "internal");
|
|
if (parNode == NULL) {
|
|
return 0;
|
|
}
|
|
AddHipadabaChild(motorNode, parNode, NULL);
|
|
i++;
|
|
}
|
|
|
|
/*
|
|
* Add the parameters in the obpar array
|
|
*/
|
|
for (i = 0; i < MOTOBPARLENGTH; i++) {
|
|
parNode = MakeMotParNode(pMot->ParArray[i].name, pMot);
|
|
if (parNode == NULL) {
|
|
return 0;
|
|
}
|
|
AddHipadabaChild(motorNode, parNode, NULL);
|
|
AddPrivProperty(parNode, pMot->ParArray[i].iCode);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static char *getDriverParList(MotorDriver * pDriv)
|
|
{
|
|
SConnection *pCon = NULL;
|
|
pDynString list = NULL;
|
|
char *listData = NULL;
|
|
|
|
if (pDriv->ListDriverPar != NULL) {
|
|
pCon = SCCreateDummyConnection(pServ->pSics);
|
|
if (pCon == NULL) {
|
|
return NULL;
|
|
}
|
|
SCStartBuffering(pCon);
|
|
pDriv->ListDriverPar(pDriv, "test.", pCon);
|
|
list = SCEndBuffering(pCon);
|
|
if (list != NULL) {
|
|
listData = strdup(GetCharArray(list));
|
|
SCDeleteConnection(pCon);
|
|
} else {
|
|
listData = NULL;
|
|
}
|
|
return listData;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
extern char *trim(char *str);
|
|
/*--------------------------------------------------------------------------*/
|
|
static char *extractName(char *line)
|
|
{
|
|
char *name = NULL, *pEnd = NULL;
|
|
|
|
name = strchr(line, '.');
|
|
assert(name != NULL);
|
|
while (*name == '.') {
|
|
name++;
|
|
}
|
|
pEnd = strchr(name, '=');
|
|
assert(pEnd != NULL);
|
|
*pEnd = '\0';
|
|
return trim(name);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static int CreateDriverParameters(pMotor pM, pHdb parent)
|
|
{
|
|
char *listPtr = NULL, line[80], *pPtr, *name;
|
|
pHdb node = NULL;
|
|
|
|
listPtr = getDriverParList(pM->pDriver);
|
|
if (listPtr == NULL) {
|
|
/*
|
|
* no driver parameters
|
|
*/
|
|
return 1;
|
|
}
|
|
pPtr = listPtr;
|
|
while ((pPtr = stptok(pPtr, line, 79, "\n")) != NULL) {
|
|
name = extractName(line);
|
|
node = MakeMotParNode(name, pM);
|
|
SetHdbProperty(node, PRIVNAM, "manager");
|
|
if (node != NULL) {
|
|
AddHipadabaChild(parent, node, NULL);
|
|
}
|
|
}
|
|
free(listPtr);
|
|
return 1;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
static pHdb CreateMotorAdapter(char *name, pMotor pMot)
|
|
{
|
|
pHdb result = NULL;
|
|
commandContext comCom;
|
|
float access;
|
|
|
|
assert(pMot != NULL);
|
|
|
|
result = MakeSICSHdbDriv(name, usUser, pMot, HIPFLOAT);
|
|
if (result == NULL) {
|
|
return NULL;
|
|
}
|
|
MotorGetPar(pMot, "accesscode", &access);
|
|
AddPrivProperty(result, (int) access);
|
|
SetHdbProperty(result, "type", "drivable");
|
|
SetHdbProperty(result, "sicsdev", pMot->name);
|
|
/*
|
|
* We want to be notified when this motor drives around. Or
|
|
* its parameters change.
|
|
*/
|
|
strlcpy(comCom.deviceID, name, 255);
|
|
comCom.transID = -77;
|
|
RegisterCallback(pMot->pCall, MOTDRIVE, MoveCallback, result, NULL);
|
|
RegisterCallback(pMot->pCall, HDBVAL, MotorValueCallback, result, NULL);
|
|
|
|
if (!AddStdMotorPar(result, pMot)) {
|
|
DeleteHipadabaNode(result, NULL);
|
|
return NULL;
|
|
}
|
|
|
|
if (!CreateDriverParameters(pMot, result)) {
|
|
DeleteHipadabaNode(result, NULL);
|
|
return NULL;
|
|
}
|
|
result->iprotected = 1;
|
|
|
|
return result;
|
|
}
|
|
|
|
/*============== histogram memory ======================================*/
|
|
static long totalSum(int *data, int length)
|
|
{
|
|
long result = 0l;
|
|
int i;
|
|
|
|
if (data == NULL) {
|
|
return 0;
|
|
}
|
|
for (i = 0; i < length; i++) {
|
|
result += data[i];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
typedef struct {
|
|
pHistMem pHM;
|
|
pHdb node;
|
|
} HMAdapter, *pHMAdapter;
|
|
/*-------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn HMDataGetCallback(pHdb currentNode,
|
|
void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
pHMAdapter pHMA = (pHMAdapter) userData;
|
|
SConnection *pCon = NULL;
|
|
long sum1;
|
|
pHdbDataMessage mm = NULL;
|
|
|
|
if ((mm = GetHdbGetMessage(message)) == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
pCon = mm->callData;
|
|
assert(pHMA != NULL && pHMA->pHM != NULL);
|
|
if (pCon == NULL) {
|
|
return hdbAbort;
|
|
}
|
|
currentNode->value.arrayLength = GetHistLength(pHMA->pHM);
|
|
currentNode->value.v.intArray =
|
|
(int *) GetHistogramPointer(pHMA->pHM, pCon);
|
|
NotifyHipadabaPar(pHMA->node, NULL);
|
|
return hdbContinue;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static int DimCallback(int iEvent, void *eventData, void *userData)
|
|
{
|
|
pHMAdapter pHMA = (pHMAdapter)userData;
|
|
|
|
if(iEvent == DIMCHANGE){
|
|
pHMA->node->value.arrayLength = GetHistLength(pHMA->pHM);
|
|
pHMA->node->value.v.intArray =
|
|
(int *) GetHistogramPointer(pHMA->pHM, pServ->dummyCon);
|
|
}
|
|
return 1;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static pHdb MakeHMDataNode(pHistMem pHM, char *name)
|
|
{
|
|
pHdb node = NULL;
|
|
pHdbCallback pCall = NULL;
|
|
pHMAdapter pHMA = NULL;
|
|
|
|
node = MakeHipadabaNode(name, HIPINTVARAR, GetHistLength(pHM));
|
|
pHMA = malloc(sizeof(HMAdapter));
|
|
if (node == NULL || pHMA == NULL) {
|
|
return NULL;
|
|
}
|
|
pHMA->pHM = pHM;
|
|
pHMA->node = node;
|
|
node->value.doNotFree = 1;
|
|
node->value.v.intArray = (int *)GetHistogramPointer(pHM, pServ->dummyCon);
|
|
pCall = MakeHipadabaCallback(HMDataGetCallback, pHMA, free);
|
|
if (pCall == NULL) {
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(node, pCall);
|
|
AppendHipadabaCallback(node, MakeReadOnlyCallback());
|
|
RegisterCallback(pHM->pCall,DIMCHANGE, DimCallback, pHMA, NULL);
|
|
return node;
|
|
}
|
|
|
|
/*================ SICS Variable ======================================*/
|
|
static hdbCallbackReturn SicsVarSetCallback(pHdb currentNode,
|
|
void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
pSicsVariable pVar = (pSicsVariable) userData;
|
|
SConnection *pCon = NULL;
|
|
int userRights = usMugger;
|
|
pHdbDataMessage mm = NULL;
|
|
|
|
if ((mm = GetHdbSetMessage(message)) == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
pCon = mm->callData;
|
|
|
|
assert(pVar != NULL);
|
|
|
|
if (pCon != NULL) {
|
|
userRights = SCGetRights(pCon);
|
|
}
|
|
switch (currentNode->value.dataType) {
|
|
case HIPINT:
|
|
VarSetInt(pVar, mm->v->v.intValue, userRights);
|
|
break;
|
|
case HIPFLOAT:
|
|
VarSetFloat(pVar, (float) mm->v->v.doubleValue, userRights);
|
|
break;
|
|
case HIPTEXT:
|
|
VarSetText(pVar, mm->v->v.text, userRights);
|
|
break;
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
static int ValueCallback(int iEvent, void *eventData, void *userData)
|
|
{
|
|
pSicsVariable pVar = (pSicsVariable) eventData;
|
|
pHdb node = (pHdb) userData;
|
|
hdbValue v;
|
|
|
|
if (iEvent == VALUECHANGE && pVar != NULL && node != NULL) {
|
|
switch (pVar->eType) {
|
|
case veInt:
|
|
v = MakeHdbInt(pVar->iVal);
|
|
break;
|
|
case veFloat:
|
|
v = MakeHdbFloat((double) pVar->fVal);
|
|
break;
|
|
case veText:
|
|
v = MakeHdbText(pVar->text);
|
|
break;
|
|
}
|
|
UpdateHipadabaPar(node, v, NULL);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
static pHdb MakeSicsVarNode(pSicsVariable pVar, char *name)
|
|
{
|
|
pHdb node = NULL;
|
|
pHdbCallback pCall = NULL;
|
|
commandContext comCom;
|
|
int type;
|
|
char command[1024];
|
|
|
|
switch (pVar->eType) {
|
|
case veInt:
|
|
type = HIPINT;
|
|
break;
|
|
case veFloat:
|
|
type = HIPFLOAT;
|
|
break;
|
|
case veText:
|
|
type = HIPTEXT;
|
|
break;
|
|
}
|
|
node = MakeHipadabaNode(name, type, 1);
|
|
if (node == NULL) {
|
|
return NULL;
|
|
}
|
|
if (pVar->iLock == 1) {
|
|
AddPrivProperty(node, usInternal);
|
|
} else {
|
|
AddPrivProperty(node, pVar->iAccessCode);
|
|
}
|
|
pCall = MakeHipadabaCallback(SicsVarSetCallback, pVar, NULL);
|
|
if (pCall == NULL) {
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(node, pCall);
|
|
RegisterCallback(pVar->pCall, VALUECHANGE, ValueCallback, node, NULL);
|
|
snprintf(command, 1023, "%s ", pVar->name);
|
|
SetHdbProperty(node, "sicscommand", command);
|
|
|
|
node->iprotected = 1;
|
|
return node;
|
|
}
|
|
|
|
/*================ counter =============================================*/
|
|
typedef struct {
|
|
pHdb node;
|
|
int monitor; /* -1 == time */
|
|
pCounter counter;
|
|
} CountEntry;
|
|
static int countList = -10;
|
|
/*---------------------------------------------------------------------*/
|
|
static void updateCountList()
|
|
{
|
|
int status;
|
|
hdbValue v;
|
|
CountEntry hugo;
|
|
long monitor;
|
|
float time;
|
|
SConnection *pDummy = NULL;
|
|
|
|
if (countList < 0) {
|
|
return;
|
|
}
|
|
pDummy = SCCreateDummyConnection(pServ->pSics);
|
|
if (pDummy == NULL) {
|
|
return;
|
|
}
|
|
|
|
status = LLDnodePtr2First(countList);
|
|
while (status != 0) {
|
|
LLDnodeDataTo(countList, &hugo);
|
|
if (hugo.monitor < 0) {
|
|
time = GetCountTime(hugo.counter, pDummy);
|
|
v = MakeHdbFloat((double) time);
|
|
UpdateHipadabaPar(hugo.node, v, NULL);
|
|
} else {
|
|
monitor = GetMonitor(hugo.counter, hugo.monitor, pDummy);
|
|
v = MakeHdbInt((int) monitor);
|
|
UpdateHipadabaPar(hugo.node, v, NULL);
|
|
}
|
|
status = LLDnodePtr2Next(countList);
|
|
}
|
|
SCDeleteConnection(pDummy);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static int CounterCallback(int iEvent, void *eventData, void *userData)
|
|
{
|
|
if (iEvent == MONITOR || iEvent == COUNTEND) {
|
|
updateCountList();
|
|
}
|
|
return 1;
|
|
}/*=================== SICSData ========================================*/
|
|
static void copyIntSicsData(pHdb node, pSICSData data)
|
|
{
|
|
if (node->value.arrayLength != data->dataUsed) {
|
|
if (node->value.v.intArray != NULL) {
|
|
free(node->value.v.intArray);
|
|
}
|
|
node->value.arrayLength = data->dataUsed;
|
|
node->value.v.intArray = malloc(data->dataUsed * sizeof(int));
|
|
if (node->value.v.intArray == NULL) {
|
|
node->value.arrayLength = 0;
|
|
return;
|
|
}
|
|
}
|
|
memcpy(node->value.v.intArray, data->data, data->dataUsed * sizeof(int));
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
static void copyFloatSicsData(pHdb node, pSICSData data)
|
|
{
|
|
int i;
|
|
float val;
|
|
|
|
if (node->value.arrayLength != data->dataUsed) {
|
|
if (node->value.v.floatArray != NULL) {
|
|
free(node->value.v.floatArray);
|
|
}
|
|
node->value.arrayLength = data->dataUsed;
|
|
node->value.v.floatArray = malloc(data->dataUsed * sizeof(double));
|
|
if (node->value.v.floatArray == NULL) {
|
|
node->value.arrayLength = 0;
|
|
return;
|
|
}
|
|
}
|
|
for (i = 0; i < data->dataUsed; i++) {
|
|
getSICSDataFloat(data, i, &val);
|
|
node->value.v.floatArray[i] = val;
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
static hdbCallbackReturn SICSDataCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
pSICSData self = (pSICSData) userData;
|
|
pHdbDataMessage mm = NULL;
|
|
int i, status;
|
|
char script[256], error[1024];
|
|
|
|
assert(self != NULL);
|
|
|
|
/*
|
|
* I have to make copies because the floats in SICSData
|
|
* are floats but doubles in Hipdaba. Siiiigggghhhh!
|
|
* But it is cleaner in some way anyway.
|
|
*/
|
|
if ((mm = GetHdbGetMessage(message)) != NULL) {
|
|
memset(script, 0, 256);
|
|
if (GetHdbProperty(node, "readscript", script, 256) == 1) {
|
|
status = Tcl_Eval(InterpGetTcl(pServ->pSics), script);
|
|
if (status != TCL_OK) {
|
|
snprintf(error, 1023, "ERROR: Tcl returned error: %s",
|
|
Tcl_GetStringResult(InterpGetTcl(pServ->pSics)));
|
|
if (mm->callData != NULL) {
|
|
SCWrite((SConnection *) mm->callData, error, eError);
|
|
return hdbAbort;
|
|
}
|
|
}
|
|
}
|
|
if (node->value.dataType == HIPINTVARAR) {
|
|
copyIntSicsData(node, self);
|
|
} else if (node->value.dataType == HIPFLOATVARAR) {
|
|
copyFloatSicsData(node, self);
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
|
|
if ((mm = GetHdbSetMessage(message)) != NULL) {
|
|
if (node->value.dataType == HIPINTVARAR) {
|
|
for (i = 0; i < mm->v->arrayLength; i++) {
|
|
setSICSDataInt(self, i, mm->v->v.intArray[i]);
|
|
}
|
|
} else if (node->value.dataType == HIPFLOATVARAR) {
|
|
for (i = 0; i < mm->v->arrayLength; i++) {
|
|
setSICSDataFloat(self, i, (float) mm->v->v.floatArray[i]);
|
|
}
|
|
}
|
|
memset(script, 0, 256);
|
|
if (GetHdbProperty(node, "writescript", script, 256) == 1) {
|
|
status = Tcl_Eval(InterpGetTcl(pServ->pSics), script);
|
|
if (status != TCL_OK) {
|
|
snprintf(error, 1023, "ERROR: Tcl returned error: %s",
|
|
Tcl_GetStringResult(InterpGetTcl(pServ->pSics)));
|
|
if (mm->callData != NULL) {
|
|
SCWrite((SConnection *) mm->callData, error, eError);
|
|
return hdbAbort;
|
|
}
|
|
}
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
|
|
return hdbContinue;
|
|
}
|
|
/*================= targets ============================================*/
|
|
typedef struct {
|
|
char *name;
|
|
pHdb node;
|
|
}TargetData, *pTargetData ;
|
|
/*----------------------------------------------------------------------*/
|
|
static void KillTargetData(void *data)
|
|
{
|
|
pTargetData self = (pTargetData) data;
|
|
if(self == NULL){
|
|
return;
|
|
}
|
|
if(self->name != NULL){
|
|
free(self->name);
|
|
}
|
|
free(self);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static int TargetCallback(int iEvent, void *pEventData, void *pUserData)
|
|
{
|
|
pTargetData user = NULL;
|
|
pNewTarget event = NULL;
|
|
hdbValue v;
|
|
|
|
if(iEvent != NEWTARGET){
|
|
return 0;
|
|
}
|
|
|
|
user = (pTargetData)pUserData;
|
|
event = (pNewTarget)pEventData;
|
|
assert(user != NULL && event != NULL);
|
|
|
|
if(strcmp(user->name,event->name) == 0){
|
|
v = MakeHdbFloat((double)event->target);
|
|
UpdateHipadabaPar(user->node, v, NULL);
|
|
}
|
|
return 1;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static int AttachTarget(SConnection *pCon, SicsInterp *pSics,
|
|
char *drivename, char *nodename)
|
|
{
|
|
pTargetData tData = NULL;
|
|
pHdb node = NULL;
|
|
pIDrivable pDriv = NULL;
|
|
CommandList *pCom = NULL;
|
|
float val;
|
|
|
|
pDriv = FindDrivable(pSics, drivename);
|
|
if(pDriv == NULL){
|
|
SCPrintf(pCon,eError,"ERROR: drivable %s not found", drivename);
|
|
return 0;
|
|
}
|
|
|
|
node = FindHdbNode(NULL, nodename, pCon);
|
|
if(node == NULL){
|
|
SCPrintf(pCon,eError,"ERROR: node %s not found", nodename);
|
|
return 0;
|
|
}
|
|
|
|
tData = malloc(sizeof(TargetData));
|
|
if(tData == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory in AttachTarget", eError);
|
|
return 0;
|
|
}
|
|
tData->name = strdup(drivename);
|
|
tData->node = node;
|
|
|
|
pCom = FindCommand(pSics,drivename);
|
|
/* This cannot fail as we already located the drivable */
|
|
GetDrivablePosition(pCom->pData, pCon,&val);
|
|
UpdateHipadabaPar(node,MakeHdbFloat(val), pCon);
|
|
|
|
RegisterCallback((pICallBack)GetExecutorCallback(pServ->pExecutor),
|
|
NEWTARGET,
|
|
TargetCallback,
|
|
tData,
|
|
KillTargetData);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/*============== interpreter function ==================================*/
|
|
int SICSHdbAdapter(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pHdb path = NULL;
|
|
pHdb node = NULL;
|
|
pMotor pMot = NULL;
|
|
pHistMem pHM = NULL;
|
|
CommandList *pCom = NULL;
|
|
pIDrivable pDriv = NULL;
|
|
pSicsVariable pVar = NULL;
|
|
char buffer[512];
|
|
pCounter pCount = NULL;
|
|
CountEntry hugo;
|
|
pSICSData data = NULL;
|
|
int type;
|
|
pHdbCallback pCall = NULL;
|
|
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
return 0;
|
|
}
|
|
if (argc < 4) {
|
|
SCWrite(pCon, "ERROR: Insufficient number of arguments", eError);
|
|
return 0;
|
|
}
|
|
|
|
if(strcmp(argv[1],"target") == 0){
|
|
return AttachTarget(pCon,pSics,argv[2], argv[3]);
|
|
}
|
|
|
|
path = FindHdbNode(NULL, argv[1], pCon);
|
|
if (path == NULL) {
|
|
SCWrite(pCon, "ERROR: path to attach object too not found", eError);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* look for motors
|
|
*/
|
|
pMot = (pMotor) FindCommandData(pSics, argv[2], "Motor");
|
|
if (pMot != NULL) {
|
|
if(pMot->ParArray == NULL){
|
|
SCWrite(pCon,"ERROR: second generation motors need to be linked rather then adapted",
|
|
eError);
|
|
return 0;
|
|
}
|
|
node = CreateMotorAdapter(argv[3], pMot);
|
|
if (node == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory creating motor node", eError);
|
|
return 0;
|
|
}
|
|
AddHipadabaChild(path, node, pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/*
|
|
* look for drivables
|
|
*/
|
|
pDriv = FindDrivable(pSics, argv[2]);
|
|
pCom = FindCommand(pSics, argv[2]);
|
|
if (pDriv != NULL && pCom != NULL && pCom->pData != NULL) {
|
|
node = MakeSICSHdbDriv(argv[3], usUser, pCom->pData, HIPFLOAT);
|
|
if (node == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory creating drivable node", eError);
|
|
return 0;
|
|
}
|
|
SetHdbProperty(node, PRIVNAM, "user");
|
|
SetHdbProperty(node, "type", "drivable");
|
|
SetHdbProperty(node, "sicsdev", argv[2]);
|
|
AddHipadabaChild(path, node, pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* look for SICS Variables
|
|
*/
|
|
pVar = (pSicsVariable) FindCommandData(pSics, argv[2], "SicsVariable");
|
|
if (pVar != NULL) {
|
|
node = MakeSicsVarNode(pVar, argv[3]);
|
|
if (node == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory creating SICS variable node",
|
|
eError);
|
|
return 0;
|
|
}
|
|
AddHipadabaChild(path, node, pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* look for histogram memories
|
|
*/
|
|
pHM = (pHistMem) FindCommandData(pSics, argv[2], "HistMem");
|
|
if (pHM != NULL) {
|
|
node = MakeHMDataNode(pHM, argv[3]);
|
|
if (node == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory creating HM node", eError);
|
|
return 0;
|
|
}
|
|
AddHipadabaChild(path, node, pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* look for counters
|
|
*/
|
|
pCount = (pCounter) FindCommandData(pSics, argv[2], "SingleCounter");
|
|
if (pCount != NULL) {
|
|
hugo.monitor = atoi(argv[3]);
|
|
hugo.counter = pCount;
|
|
hugo.node = path;
|
|
if (countList < 0) {
|
|
countList = LLDcreate(sizeof(CountEntry));
|
|
RegisterCallback(pCount->pCall,
|
|
COUNTSTART, CounterCallback, NULL, NULL);
|
|
RegisterCallback(pCount->pCall,
|
|
COUNTEND, CounterCallback, NULL, NULL);
|
|
RegisterCallback(pCount->pCall,
|
|
MONITOR, CounterCallback, NULL, NULL);
|
|
}
|
|
LLDnodeAppendFrom(countList, &hugo);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* look for SICSData
|
|
*/
|
|
data = (pSICSData) FindCommandData(pSics, argv[2], "SICSData");
|
|
if (data != NULL) {
|
|
if (argc < 5) {
|
|
SCWrite(pCon, "ERROR: need type and name to create SICSData adapter",
|
|
eError);
|
|
return 0;
|
|
}
|
|
type = convertHdbType(argv[3]);
|
|
if (type != HIPINTVARAR && type != HIPFLOATVARAR) {
|
|
SCWrite(pCon,
|
|
"ERROR: need intvarar or floatvarar type for SICSData adapter",
|
|
eError);
|
|
return 0;
|
|
}
|
|
node = MakeHipadabaNode(argv[4], type, 0);
|
|
if (node == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory in SICSHdbAdapter", eError);
|
|
return 0;
|
|
}
|
|
pCall = MakeHipadabaCallback(SICSDataCallback, data, NULL);
|
|
if (pCall == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory in SICSHdbAdapter", eError);
|
|
return 0;
|
|
}
|
|
AppendHipadabaCallback(node, pCall);
|
|
AddHipadabaChild(path, node, pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
|
|
snprintf(buffer, 511,
|
|
"ERROR: attaching this type of object: %s at %s not implemented",
|
|
argv[2], argv[1]);
|
|
SCWrite(pCon, buffer, eError);
|
|
return 0;
|
|
}
|
|
|
|
/*====================== SubSample =========================================*/
|
|
int HdbSubSample(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pHistMem pHM = NULL;
|
|
pHdb node = NULL;
|
|
int bank = 0, length = -1, status, i;
|
|
HistInt *data = NULL;
|
|
char *pPtr = NULL;
|
|
char error[132];
|
|
hdbValue v;
|
|
HMdata hdata;
|
|
pHdb hmnode = NULL;
|
|
|
|
if (argc < 4) {
|
|
SCWrite(pCon,
|
|
"ERROR: insufficient number of arguments to HdbSubSample",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
pPtr = strchr(argv[1], ':');
|
|
if (pPtr != NULL) {
|
|
*pPtr = '\0';
|
|
pPtr++;
|
|
sscanf(pPtr, "%d", &bank);
|
|
}
|
|
node = FindHdbNode(NULL, argv[2], pCon);
|
|
if (node == NULL) {
|
|
SCWrite(pCon, "ERROR: node not found!",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
old HM
|
|
*/
|
|
pHM = (pHistMem) FindCommandData(pSics, argv[1], "HistMem");
|
|
if(pHM != NULL){
|
|
|
|
if (pHM->pDriv->SubSample == NULL) {
|
|
SCWrite(pCon, "ERROR: hm does not support subsampling", eError);
|
|
return 0;
|
|
}
|
|
data = pHM->pDriv->SubSample(pHM->pDriv, pCon, bank, argv[3]);
|
|
if (data == NULL) {
|
|
SCWrite(pCon, "ERROR: sub sampling failed", eError);
|
|
return 0;
|
|
}
|
|
}
|
|
/*
|
|
new HM
|
|
*/
|
|
pHM = (pHistMem) FindCommandData(pSics, argv[1], "HistMemSec");
|
|
if(pHM != NULL){
|
|
memset(&hdata,0,sizeof(HMdata));
|
|
hmnode = GetHipadabaNode(pHM->pDes->parNode,"dim");
|
|
if(hmnode == NULL){
|
|
SCWrite(pCon,"ERROR: dim node not found",eError);
|
|
return 0;
|
|
}
|
|
hdata.rank = hmnode->value.arrayLength;
|
|
for(i = 0; i < hdata.rank; i++){
|
|
hdata.iDim[i] = hmnode->value.v.intArray[i];
|
|
}
|
|
hmnode = GetHipadabaNode(pHM->pDes->parNode,"data");
|
|
if(hmnode == NULL){
|
|
SCWrite(pCon,"ERROR: data node not found",eError);
|
|
return 0;
|
|
}
|
|
hdata.localBuffer = hmnode->value.v.intArray;
|
|
data = subSample(&hdata, argv[3], error, sizeof(error));
|
|
if(data == NULL){
|
|
SCPrintf(pCon,eError,"ERROR: %s while processing %s with %s",
|
|
error, argv[1], argv[3]);
|
|
return 0;
|
|
}
|
|
} else {
|
|
SCPrintf(pCon,eError,"ERROR: hm %s not found", argv[1]);
|
|
return 0;
|
|
}
|
|
|
|
|
|
v.dataType = HIPINTVARAR;
|
|
v.arrayLength = data[0];
|
|
v.v.intArray = data + 1;
|
|
|
|
UpdateHipadabaPar(node, v, pCon);
|
|
free(data);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|