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