Files
sics/proxy.c

502 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 {
strlcpy(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,
pCon->runLevel, (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;
if (GetHdbKillNodeMessage(message) != NULL) {
return hdbContinue;
}
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;
}