/** * 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 #include #include /*-----------------------------------------------------------------------*/ 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; }