473 lines
13 KiB
C
473 lines
13 KiB
C
/**
|
|
* This is the implementation of a SICS object which really is a placeholder
|
|
* for another one. It shall be used in Hipadaba for sample enviornment
|
|
* devices. This is also the reason why the objectNode is supposed to be
|
|
* double.
|
|
*
|
|
* copyright: see file COPYRIGHT
|
|
*
|
|
* Mark Koennecke, March 2008
|
|
*
|
|
*/
|
|
#include <sics.h>
|
|
#include <sicsobj.h>
|
|
#include <sicshipadaba.h>
|
|
/*-----------------------------------------------------------------------*/
|
|
typedef struct {
|
|
pIDrivable pDriv;
|
|
pEVInterface pEnv;
|
|
pIDrivable pSlaveDriv;
|
|
void *slaveData;
|
|
pEVInterface pEnvSlave;
|
|
} ProxyInt, *pProxyInt;
|
|
/*------------------------------------------------------------------------*/
|
|
static void KillProxyInt(void *data){
|
|
pProxyInt proxy = (pProxyInt)data;
|
|
|
|
if(proxy == NULL){
|
|
return;
|
|
}
|
|
if(proxy->pDriv != NULL){
|
|
free(proxy->pDriv);
|
|
}
|
|
if(proxy->pEnv != NULL){
|
|
free(proxy->pEnv);
|
|
}
|
|
free(proxy);
|
|
}
|
|
/*===================== Drivable Interfaces ================================*/
|
|
static int testDrivProxy(pSICSOBJ self){
|
|
pProxyInt proxy = self->pPrivate;
|
|
|
|
if(proxy->pSlaveDriv != NULL && proxy->slaveData != NULL){
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
static int ProxyHalt(void *data){
|
|
pSICSOBJ self = (pSICSOBJ)data;
|
|
pProxyInt proxy = NULL;
|
|
|
|
assert(self != NULL);
|
|
proxy = self->pPrivate;
|
|
assert(self != NULL);
|
|
|
|
if(testDrivProxy(self)){
|
|
return proxy->pSlaveDriv->Halt(proxy->slaveData);
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static int ProxyLimits(void *data, float fval,
|
|
char *error, int iErrLen){
|
|
pSICSOBJ self = (pSICSOBJ)data;
|
|
pProxyInt proxy = NULL;
|
|
|
|
assert(self != NULL);
|
|
proxy = self->pPrivate;
|
|
assert(self != NULL);
|
|
|
|
if(testDrivProxy(self)){
|
|
return proxy->pSlaveDriv->CheckLimits(proxy->slaveData, fval,
|
|
error, iErrLen);
|
|
} else {
|
|
strncpy(error,"ERROR: device not configured",iErrLen);
|
|
return 0;
|
|
}
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
static long ProxySet(void *data, SConnection *pCon, float fVal){
|
|
pSICSOBJ self = (pSICSOBJ)data;
|
|
pProxyInt proxy = NULL;
|
|
|
|
assert(self != NULL);
|
|
proxy = self->pPrivate;
|
|
assert(self != NULL);
|
|
|
|
if(testDrivProxy(self)){
|
|
return proxy->pSlaveDriv->SetValue(proxy->slaveData,
|
|
pCon, fVal);
|
|
} else {
|
|
SCWrite(pCon,"ERROR: device not configured", eError);
|
|
return 0;
|
|
}
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
static int ProxyStatus(void *data, SConnection *pCon){
|
|
pSICSOBJ self = (pSICSOBJ)data;
|
|
pProxyInt proxy = NULL;
|
|
|
|
assert(self != NULL);
|
|
proxy = self->pPrivate;
|
|
assert(self != NULL);
|
|
|
|
if(testDrivProxy(self)){
|
|
return proxy->pSlaveDriv->CheckStatus(proxy->slaveData,
|
|
pCon);
|
|
} else {
|
|
SCWrite(pCon,"ERROR: device not configured", eError);
|
|
return HWFault;
|
|
}
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
static float ProxyGet(void *data, SConnection *pCon){
|
|
pSICSOBJ self = (pSICSOBJ)data;
|
|
pProxyInt proxy = NULL;
|
|
|
|
assert(self != NULL);
|
|
proxy = self->pPrivate;
|
|
assert(self != NULL);
|
|
|
|
if(testDrivProxy(self)){
|
|
return proxy->pSlaveDriv->GetValue(proxy->slaveData, pCon);
|
|
} else {
|
|
SCWrite(pCon,"ERROR: device not configured", eError);
|
|
return HWFault;
|
|
}
|
|
}
|
|
/*===================== environment interface ==========================*/
|
|
static int testEnvProxy(pSICSOBJ self){
|
|
pProxyInt proxy = self->pPrivate;
|
|
|
|
if(proxy->pEnvSlave != NULL && proxy->slaveData != NULL){
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
static EVMode ProxyMode(void *data){
|
|
pSICSOBJ self = (pSICSOBJ)data;
|
|
pProxyInt proxy = NULL;
|
|
|
|
assert(self != NULL);
|
|
proxy = self->pPrivate;
|
|
assert(self != NULL);
|
|
|
|
if(testEnvProxy(self)){
|
|
return proxy->pEnvSlave->GetMode(proxy->slaveData);
|
|
} else {
|
|
return EVError;
|
|
}
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static int ProxyTolerance(void *data){
|
|
pSICSOBJ self = (pSICSOBJ)data;
|
|
pProxyInt proxy = NULL;
|
|
|
|
assert(self != NULL);
|
|
proxy = self->pPrivate;
|
|
assert(self != NULL);
|
|
|
|
if(testEnvProxy(self)){
|
|
return proxy->pEnvSlave->IsInTolerance(proxy->slaveData);
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static int ProxyError(void *data){
|
|
pSICSOBJ self = (pSICSOBJ)data;
|
|
pProxyInt proxy = NULL;
|
|
|
|
assert(self != NULL);
|
|
proxy = self->pPrivate;
|
|
assert(self != NULL);
|
|
|
|
if(testEnvProxy(self)){
|
|
return proxy->pEnvSlave->HandleError(proxy->slaveData);
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
static void *findRealDev(pHdb node){
|
|
char realDevice[80];
|
|
CommandList *pCom = NULL;
|
|
|
|
GetHdbProperty(node,"proxy",realDevice,80);
|
|
pCom = FindCommand(pServ->pSics,realDevice);
|
|
if(pCom != NULL){
|
|
return pCom->pData;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
static void *ProxyGetInterface(void *pData, int iID){
|
|
pSICSOBJ self = (pSICSOBJ)pData;
|
|
pDummy other = NULL;
|
|
void *inter = NULL;
|
|
pProxyInt proxy = NULL;
|
|
|
|
assert(self != NULL);
|
|
proxy = self->pPrivate;
|
|
|
|
if(self != NULL){
|
|
other = (pDummy)findRealDev(self->objectNode);
|
|
if(other != NULL){
|
|
inter = other->pDescriptor->GetInterface(other, iID);
|
|
if(inter == NULL &&
|
|
(iID == DRIVEID || iID == ENVIRINTERFACE) ){
|
|
proxy->pEnvSlave = NULL;
|
|
proxy->pSlaveDriv = NULL;
|
|
proxy->slaveData = NULL;
|
|
return NULL;
|
|
} else {
|
|
if(iID == DRIVEID){
|
|
proxy->pSlaveDriv = inter;
|
|
proxy->slaveData = other;
|
|
return proxy->pDriv;
|
|
} else if(iID == ENVIRINTERFACE){
|
|
proxy->pEnvSlave = inter;
|
|
proxy->slaveData = other;
|
|
return proxy->pEnv;
|
|
}
|
|
}
|
|
return inter;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn ProxyCallback(pHdb node, void *userData,
|
|
pHdbMessage message){
|
|
pHdbDataMessage get = NULL, set = NULL;
|
|
pDummy other = NULL;
|
|
pIDrivable pDriv = NULL;
|
|
float fval;
|
|
int status;
|
|
SConnection *pCon = NULL;
|
|
pSICSOBJ self = (pSICSOBJ)userData;
|
|
char proxyDev[80];
|
|
|
|
get = GetHdbGetMessage(message);
|
|
if(get != NULL){
|
|
pCon = (SConnection *)get->callData;
|
|
other = (pDummy)findRealDev(node);
|
|
if(other != NULL){
|
|
pDriv = other->pDescriptor->GetInterface(other,DRIVEID);
|
|
if(pDriv != NULL && pCon != NULL){
|
|
fval = pDriv->GetValue(other, pCon);
|
|
get->v->v.doubleValue = (double)fval;
|
|
node->value.v.doubleValue = (double)fval;
|
|
return hdbContinue;
|
|
}
|
|
}
|
|
get->v->v.doubleValue = .0;
|
|
}
|
|
|
|
set = GetHdbSetMessage(message);
|
|
if(set != NULL){
|
|
pCon = (SConnection *)set->callData;
|
|
other = (pDummy)findRealDev(node);
|
|
if(other == NULL){
|
|
if(pCon != NULL){
|
|
SCWrite(pCon,"ERROR: device not configured", eError);
|
|
return hdbAbort;
|
|
}
|
|
}
|
|
GetHdbProperty(node,"proxy", proxyDev,80);
|
|
status = StartDevice(pServ->pExecutor, proxyDev,
|
|
self->pDes, self, pCon, (float)set->v->v.doubleValue);
|
|
if(status == 1){
|
|
return hdbContinue;
|
|
} else {
|
|
return hdbAbort;
|
|
}
|
|
}
|
|
|
|
return hdbContinue;
|
|
}
|
|
/*----------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn MapParCallback(pHdb node, void *userData,
|
|
pHdbMessage message){
|
|
pHdbDataMessage get = NULL, set = NULL;
|
|
CommandList *pCom = NULL;
|
|
SConnection *pCon = NULL;
|
|
char mapPar[80], proxyDev[80], *pData = NULL;
|
|
char command[1024];
|
|
pDynString data = NULL;
|
|
|
|
GetHdbProperty(node->mama, "proxy", proxyDev,80);
|
|
pCom = FindCommand(pServ->pSics, proxyDev);
|
|
if(pCom == NULL){
|
|
if(pCon != NULL){
|
|
SCWrite(pCon,"ERROR: device not configured", eError);
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
GetHdbProperty(node,"mappar", mapPar, 80);
|
|
|
|
get = GetHdbGetMessage(message);
|
|
if(get != NULL){
|
|
pCon = (SConnection *)get->callData; snprintf(command,1024,"%s %s", proxyDev, mapPar);
|
|
if(pCon != NULL){
|
|
SCStartBuffering(pCon);
|
|
InterpExecute(pServ->pSics, pCon,command);
|
|
data = SCEndBuffering(pCon);
|
|
if(data != NULL){
|
|
pData = GetCharArray(data);
|
|
if(strstr(pData,"ERROR") != NULL){
|
|
SCWrite(pCon,pData,eError);
|
|
} else {
|
|
pData = strchr(pData,(int)'=');
|
|
if(pData != NULL){
|
|
pData++;
|
|
if(!readHdbValue(get->v, pData, command, 1024)){
|
|
SCWrite(pCon, command, eError);
|
|
}
|
|
copyHdbValue(get->v, &node->value);
|
|
return hdbContinue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
set = GetHdbSetMessage(message);
|
|
if(set != NULL){
|
|
pCon = (SConnection *)set->callData;
|
|
data = formatValue(*(set->v), node);
|
|
if(data != NULL){
|
|
snprintf(command,1024,"%s %s %s", proxyDev, mapPar,
|
|
GetCharArray(data));
|
|
DeleteDynString(data);
|
|
InterpExecute(pServ->pSics, pCon, command);
|
|
}
|
|
}
|
|
|
|
return hdbContinue;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static int MapFunc(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
|
pHdb par[], int nPar){
|
|
pHdb node = NULL;
|
|
int type;
|
|
|
|
if(nPar < 4){
|
|
SCWrite(pCon,"ERROR: not enough arguments to MapFunc", eError);
|
|
return 0;
|
|
}
|
|
|
|
type = convertHdbType(par[2]->value.v.text);
|
|
node = MakeHipadabaNode(par[0]->value.v.text, type, 1);
|
|
if(node == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory in MapFunc", eError);
|
|
return 0;
|
|
}
|
|
SetHdbProperty(node,"mappar", par[1]->value.v.text);
|
|
SetHdbProperty(node,"priv", par[3]->value.v.text);
|
|
AppendHipadabaCallback(node,
|
|
MakeHipadabaCallback(MapParCallback, NULL, NULL));
|
|
AddHipadabaChild(self->objectNode, node, pCon);
|
|
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int ProxyAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[]){
|
|
int status;
|
|
pSICSOBJ self = (pSICSOBJ)pData;
|
|
CommandList *pCom = NULL;
|
|
char proxyObj[80];
|
|
|
|
assert(self != NULL);
|
|
|
|
/*
|
|
* do parameters and object functions
|
|
*/
|
|
if(argc > 1){
|
|
status = InvokeSICSOBJ(pCon, pSics, pData, argc, argv);
|
|
if(status != -1 ){
|
|
return status;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* try the interpreter function of the proxy object
|
|
*/
|
|
GetHdbProperty(self->objectNode,"proxy", proxyObj, 80);
|
|
pCom = FindCommand(pSics, proxyObj);
|
|
if(pCom != NULL){
|
|
return pCom->OFunc(pCon,pSics,pCom->pData, argc, argv);
|
|
} else {
|
|
SCWrite(pCon,"ERROR: device not configured", eError);
|
|
return 0;
|
|
}
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int ProxyFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[]){
|
|
int type;
|
|
pSICSOBJ pNew = NULL;
|
|
pHdb mapFunc = NULL;
|
|
hdbValue v;
|
|
pProxyInt proxy = NULL;
|
|
|
|
if(argc < 4){
|
|
SCWrite(pCon,"ERROR: not enough arguments for ProxyFactory",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
type = convertHdbType(argv[3]);
|
|
pNew = MakeSICSOBJv(argv[1], "ProxyObject", type, usSpy);
|
|
if(pNew == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory in ProxyFactory",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
proxy = malloc(sizeof(ProxyInt));
|
|
if(proxy == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory in ProxyFactory",
|
|
eError);
|
|
return 0;
|
|
}
|
|
memset(proxy,0,sizeof(ProxyInt));
|
|
proxy->pDriv = CreateDrivableInterface();
|
|
proxy->pEnv = CreateEVInterface();
|
|
if(proxy->pDriv == NULL && proxy->pEnv == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory in ProxyFactory",
|
|
eError);
|
|
return 0;
|
|
}
|
|
proxy->pDriv->CheckLimits = ProxyLimits;
|
|
proxy->pDriv->CheckStatus = ProxyStatus;
|
|
proxy->pDriv->GetValue = ProxyGet;
|
|
proxy->pDriv->Halt = ProxyHalt;
|
|
proxy->pDriv->SetValue = ProxySet;
|
|
|
|
proxy->pEnv->GetMode = ProxyMode;
|
|
proxy->pEnv->HandleError = ProxyError;
|
|
proxy->pEnv->IsInTolerance = ProxyTolerance;
|
|
|
|
pNew->KillPrivate = KillProxyInt;
|
|
pNew->pPrivate = proxy;
|
|
|
|
pNew->pDes->GetInterface = ProxyGetInterface;
|
|
SetHdbProperty(pNew->objectNode, "proxy", argv[2]);
|
|
AppendHipadabaCallback(pNew->objectNode,
|
|
MakeHipadabaCallback(ProxyCallback, pNew,NULL));
|
|
|
|
v = MakeSICSFunc(MapFunc);
|
|
mapFunc = MakeSICSHdbPar("map", usMugger, v);
|
|
SetHdbProperty(mapFunc,"visible","false");
|
|
v = MakeHdbText("Undefined");
|
|
AddSICSHdbPar(mapFunc,"name",usMugger,v);
|
|
AddSICSHdbPar(mapFunc,"target",usMugger,v);
|
|
AddSICSHdbPar(mapFunc,"type",usMugger,v);
|
|
AddSICSHdbPar(mapFunc,"priv",usMugger,v);
|
|
AddHipadabaChild(pNew->objectNode, mapFunc, pCon);
|
|
|
|
AddCommand(pSics,argv[1],
|
|
ProxyAction,
|
|
KillSICSOBJ,
|
|
pNew);
|
|
|
|
return 1;
|
|
}
|
|
|