Files
sics/proxy.c
zolliker b03ddddd8f - add MskeSICSFunc
- changed return value of AddSICSHdbPar et al.
2008-05-15 07:43:05 +00:00

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;
}