Files
sics/evcontroller.c
cvs d782d43951 - added backwards calculation of hkl from four circle angles. This
required inclusion of a matrix package.
- modified  counter error handling to send a Stop when the _BAD_BUSY
  error is received.
- added an environment interface to the general controller stuff in choco.*
  Also added setting a parameter directly at the controller object.
- Added a driver for the ETH High Temperature Furnace to be used at
  SANS.
2000-07-12 12:01:19 +00:00

1438 lines
42 KiB
C

/*---------------------------------------------------------------------------
E N V I R O N M E N T C O N T R O L L E R
This is the implementation file for a base class for all environement
control devices in SICS.
Mark Koennecke, Juli 1997
Copyright:
Labor fuer Neutronenstreuung
Paul Scherrer Institut
CH-5423 Villigen-PSI
The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose, provided
that existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions. No written agreement,
license, or royalty fee is required for any of the authorized uses.
Modifications to this software may be copyrighted by their authors
and need not follow the licensing terms described here, provided that
the new terms are clearly indicated on the first page of each file where
they apply.
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.
----------------------------------------------------------------------------*/
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <tcl.h>
#include "fortify.h"
#include "splitter.h"
#include "sics.h"
#include "obpar.h"
#include "devexec.h"
#include "nserver.h"
#include "interrupt.h"
#include "emon.h"
#include "varlog.h"
#include "evcontroller.h"
#include "evcontroller.i"
#include "evdriver.i"
#include "simev.h"
#include "itc4.h"
#include "dilludriv.h"
#include "tclev.h"
#include "bruker.h"
#include "ltc11.h"
#include "eurodriv.h"
#include "el755driv.h"
#include "tecsdriv.h"
#include "chadapter.h"
/*--------------------- Functions needed to implement interfaces -----------*/
static long EVIDrive(void *pData, SConnection *pCon, float fVal)
{
pEVControl self = NULL;
int iRet, iCode, i, iFix;
char pError[132], pBueffel[256];
self = (pEVControl)pData;
assert(self);
assert(pCon);
self->fTarget = fVal;
self->eMode = EVDrive;
self->iStop = 0;
/* try at least three times to do it */
for(i = 0; i < 3; i++)
{
iRet = self->pDriv->SetValue(self->pDriv,fVal);
if(!iRet)
{
self->pDriv->GetError(self->pDriv,&iCode, pError,131);
iFix = self->pDriv->TryFixIt(self->pDriv,iCode);
switch(iFix)
{
case DEVOK:
return 1;
break;
case DEVFAULT:
sprintf(pBueffel,"ERROR: %s",pError);
SCWrite(pCon,pBueffel,eError);
return 0;
case DEVREDO:
sprintf(pBueffel,"WARNING: Fixing problem %s",pError);
SCWrite(pCon,pBueffel,eWarning);
break;
}
}
else
{
return 1;
}
}
SCWrite(pCon,"ERROR: Failed to fix previous problems, Device Error",
eError);
return 0;
}
/*---------------------------------------------------------------------------*/
static float EVIGet(void *pData, SConnection *pCon)
{
pEVControl self = NULL;
int iRet, iCode, i, iFix;
char pError[132], pBueffel[256];
float fPos = -999.;
int iPendingCount = 0;
self = (pEVControl)pData;
assert(self);
assert(pCon);
/* try at least three times to do it */
for(i = 0; i < 5; i++)
{
iRet = self->pDriv->GetValue(self->pDriv,&fPos);
if(iRet == 0)
{
self->pDriv->GetError(self->pDriv,&iCode, pError,131);
iFix = self->pDriv->TryFixIt(self->pDriv,iCode);
switch(iFix)
{
case DEVOK:
return fPos;
break;
case DEVFAULT:
sprintf(pBueffel,"ERROR: %s",pError);
SCWrite(pCon,pBueffel,eError);
return -999.;
case DEVREDO:
sprintf(pBueffel,"WARNING: Fixing problem %s",pError);
SCWrite(pCon,pBueffel,eWarning);
break;
}
}
else if(iRet == -1 ) /* pending */
{
i--;
iPendingCount++;
if(iPendingCount > 300)
{
SCWrite(pCon,"ERROR: cannot get data from socket",eError);
return -999.;
}
}
else
{
return fPos;
}
}
SCWrite(pCon,"ERROR: Failed to fix previous problems, Device Error",
eError);
return -999.;
}
/*---------------------------------------------------------------------------*/
static int EVIStatus(void *pData, SConnection *pCon)
{
pEVControl self = NULL;
float fPos, fDelta;
int iRet, iCode, iFix;
char pBueffel[256], pError[132];
static int iCount;
self = (pEVControl)pData;
assert(self);
assert(pCon);
/* go to idle when stopped */
if(self->iStop)
{
return HWIdle;
}
/* get the current position */
iRet = self->pDriv->GetValue(self->pDriv,&fPos);
if(iRet == 0)
{
self->pDriv->GetError(self->pDriv,&iCode, pError,131);
iFix = self->pDriv->TryFixIt(self->pDriv,iCode);
switch(iFix)
{
case DEVOK:
return HWBusy;
break;
case DEVFAULT:
sprintf(pBueffel,"ERROR: %s",pError);
SCWrite(pCon,pBueffel,eError);
return HWFault;
case DEVREDO:
sprintf(pBueffel,"WARNING: Fixing problem %s",pError);
SCWrite(pCon,pBueffel,eWarning);
return HWBusy;
break;
}
}
else if(iRet == -1 ) /* pending */
{
return HWBusy;
}
if(fPos < -990.)
{
sprintf(pBueffel,"ERROR: %s cannot read its current value",
self->pName);
SCWrite(pCon,pBueffel,eError);
self->eMode = EVIdle;
return HWFault;
}
/* calculate difference to target */
fDelta = self->fTarget - fPos;
if(fDelta < 0.)
{
fDelta = - fDelta;
}
/* based on this: logic ! */
if(fDelta <= ObVal(self->pParam, TOLERANCE)) /* done */
{
iCount++;
if(iCount > 3)
{
self->eMode = EVMonitor;
return HWIdle;
}
else
{
return HWBusy;
}
}
else
{
iCount = 0;
return HWBusy;
}
self->eMode = EVIdle;
return HWFault;
}
/*--------------------------------------------------------------------------*/
static int EVILimits(void *pData, float fVal, char *pError, int iErrLen)
{
pEVControl self = NULL;
char pBueffel[256];
self = (pEVControl)pData;
assert(self);
/* lower limit */
if( fVal < ObVal(self->pParam, LOWLIMIT))
{
sprintf(pBueffel,"ERROR: %f violates lower limit of device",fVal);
strncpy(pError,pBueffel,iErrLen);
return 0;
}
/* upper limit */
if( fVal > ObVal(self->pParam, UPLIMIT))
{
sprintf(pBueffel,"ERROR: %f violates upper limit of device",fVal);
strncpy(pError,pBueffel,iErrLen);
return 0;
}
/* OK */
return 1;
}
/*---------------------------------------------------------------------------*/
static int EVIHalt(void *pData)
{
pEVControl self = NULL;
float fPos;
int iRet, iRes;
self = (pEVControl)pData;
assert(self);
iRes = 1;
self->eMode = EVIdle;
self->iStop = 1;
return iRes;
}
/*---------------------------- Error Handlers --------------------------------*/
static int ErrLazy(void *pData)
{
pEVControl self = NULL;
pExeList pExe;
SConnection *pCon = NULL;
float fPos;
char pBueffel[256];
self = (pEVControl)pData;
assert(self);
self->pDriv->GetValue(self->pDriv,&fPos);
sprintf(pBueffel,"WARNING: %s is out of range by %f",self->pName,
self->fTarget - fPos);
pExe = GetExecutor();
pCon = GetExeOwner(pExe);
if(!self->iWarned)
{
if(pCon)
{
SCWrite(pCon,pBueffel,eWarning);
}
else
{
ServerWriteGlobal(pBueffel,eWarning);
}
}
self->iWarned = 1;
return 1;
}
/*--------------------------------------------------------------------------*/
static int ErrPause(void *pData)
{
pEVControl self = NULL;
pExeList pExe;
SConnection *pCon = NULL;
float fPos;
char pBueffel[256];
int iRet;
self = (pEVControl)pData;
assert(self);
self->pDriv->GetValue(self->pDriv,&fPos);
sprintf(pBueffel,"WARNING: %s is out of range by %f",self->pName,
self->fTarget - fPos);
pExe = GetExecutor();
pCon = GetExeOwner(pExe);
if(!self->iWarned)
{
if(pCon)
{
SCWrite(pCon,pBueffel,eWarning);
}
else
{
ServerWriteGlobal(pBueffel,eWarning);
}
}
self->iWarned = 1;
if(IsCounting(pExe))
{
SCWrite(GetExeOwner(pExe),"Pausing till OK",eError);
PauseExecution(pExe);
/* wait till OK */
iRet = 0;
while(iRet == 0)
{
SicsWait(5);
iRet = self->pEnvir->IsInTolerance(self);
}
/* OK now, continue */
ContinueExecution(pExe);
return 1;
}
return 1;
}
/*---------------------------------------------------------------------------*/
static int ErrInterrupt(void *pData)
{
pEVControl self = NULL;
pExeList pExe;
SConnection *pCon = NULL;
float fPos;
char pBueffel[256];
int iRet;
self = (pEVControl)pData;
assert(self);
/* report problem */
self->pDriv->GetValue(self->pDriv,&fPos);
sprintf(pBueffel,"WARNING: %s is out of range by %f",self->pName,
self->fTarget - fPos);
pExe = GetExecutor();
pCon = GetExeOwner(pExe);
if(!self->iWarned)
{
if(pCon)
{
SCWrite(pCon,pBueffel,eWarning);
}
else
{
ServerWriteGlobal(pBueffel,eWarning);
}
}
self->iWarned = 1;
/* interrupt */
SetInterrupt((int)ObVal(self->pParam,INTERRUPT));
return 1;
}
/*---------------------------------------------------------------------------*/
static int ErrRun(void *pData)
{
pEVControl self = NULL;
pExeList pExe;
SConnection *pCon = NULL;
float fPos;
char pBueffel[256];
int iRet;
self = (pEVControl)pData;
assert(self);
/* report problem */
self->pDriv->GetValue(self->pDriv,&fPos);
sprintf(pBueffel,"WARNING: %s is out of range by %f",self->pName,
self->fTarget - fPos);
pExe = GetExecutor();
pCon = GetExeOwner(pExe);
if(pCon)
{
SCWrite(pCon,pBueffel,eWarning);
SCWrite(pCon,"Driving to a safe place",eWarning);
}
else
{
ServerWriteGlobal(pBueffel,eWarning);
ServerWriteGlobal("Driving to a safe place",eWarning);
}
self->pDriv->SetValue(self->pDriv, ObVal(self->pParam,SAFEVALUE));
self->eMode = EVIdle;
return 1;
}
/*---------------------------------------------------------------------------*/
static int EVIErrHandler(void *pData)
{
pEVControl self = NULL;
int iRet, iHandler, iStatus;
self = (pEVControl)pData;
assert(self);
/* select an error handler according to the variable set
in Controller
*/
iHandler = (int)ObVal(self->pParam, ERRORHANDLER);
self->eMode = EVError;
switch(iHandler)
{
case 0: /* no op */
iStatus = ErrLazy(pData);
break;
case 1: /* Pause */
iStatus = ErrPause(pData);
break;
case 2: /* Interrupt */
iStatus = ErrInterrupt(pData);
break;
case 3: /* run to a safe place, put him into idle afterwards */
iStatus = ErrRun(pData);
return iStatus;
break;
default:
return 0;
}
/* reset mode to monitor again! */
self->eMode = EVMonitor;
return iStatus;
}
/*---------------------------------------------------------------------------*/
static EVMode EVIGetMode(void *pData)
{
pEVControl self = NULL;
self = (pEVControl)pData;
assert(self);
return self->eMode;
}
/*--------------------------------------------------------------------------*/
static int EVIIsInTolerance(void *pData)
{
pEVControl self = NULL;
float fPos, fDelta;
int iRet, iCode, iStat;
char pError[10], pBueffel[512];
pExeList pExe = NULL;
SConnection *pCon = NULL;
self = (pEVControl)pData;
assert(self);
iRet = self->pDriv->GetValue(self->pDriv, &fPos);
if( iRet == 1 )
{
if(self->iLog)
{
VarlogAdd(self->pLog, fPos);
}
fDelta = self->fTarget - fPos;
if(fDelta < 0.)
{
fDelta = -fDelta;
}
if(fDelta < ObVal(self->pParam,TOLERANCE))
{
self->eMode = EVMonitor;
if(self->iWarned)
{
pExe = GetExecutor();
pCon = GetExeOwner(pExe);
sprintf(pBueffel,"Environment device %s back in tolerances again",
self->pName);
if(pCon)
{
SCWrite(pCon,pBueffel,eWarning);
}
else
{
ServerWriteGlobal(pBueffel,eWarning);
}
self->iWarned = 0;
}
return 1;
}
else
{
return 0;
}
}
else if(iRet == -1) /* pending */
{
/* pending means OK to me */
return 1;
}
else
{
/* break down of connection to a environment device has to be
considered a problem as well
*/
self->pDriv->GetError(self->pDriv, &iCode,pError,9);
iStat = self->pDriv->TryFixIt(self->pDriv, iCode);
if( (iStat == DEVOK) || (iStat == DEVREDO) )
{
return 1; /* effectively a redo in some time */
}
else
{
return 0;
}
}
return 0;
}
/*-------------------------------------------------------------------------*/
static void *EVIInterface(void *pData, int iCode)
{
pEVControl self = NULL;
self = (pEVControl)pData;
assert(self);
if(iCode == DRIVEID)
{
return self->pDrivInt;
}
else if(iCode == ENVIRINTERFACE)
{
return self->pEnvir;
}
return NULL;
}
/*-------- All this done, we can actually implement the controller ---------*/
pEVControl CreateEVController(pEVDriver pDriv, char *pName, int *iErr)
{
pEVControl pRes = NULL;
int iRet;
assert(pDriv);
*iErr = 1;
/* new memory first */
pRes = (pEVControl)malloc(sizeof(EVControl));
if(!pRes)
{
return NULL;
}
memset(pRes,0,sizeof(EVControl));
/* new Object Descriptor */
pRes->pDes = CreateDescriptor("Environment Controller");
if(!pRes->pDes)
{
free(pRes);
return NULL;
}
pRes->pDes->GetInterface = EVIInterface;
/* new Drivable interface */
pRes->pDrivInt = CreateDrivableInterface();
if(!pRes->pDrivInt)
{
DeleteDescriptor(pRes->pDes);
free(pRes);
return NULL;
}
pRes->pDrivInt->Halt = EVIHalt;
pRes->pDrivInt->CheckLimits = EVILimits;
pRes->pDrivInt->SetValue = EVIDrive;
pRes->pDrivInt->CheckStatus = EVIStatus;
pRes->pDrivInt->GetValue = EVIGet;
/* new environment interface */
pRes->pEnvir = CreateEVInterface();
if(!pRes->pEnvir)
{
free(pRes->pDrivInt);
DeleteDescriptor(pRes->pDes);
free(pRes);
return NULL;
}
pRes->pEnvir->GetMode = EVIGetMode;
pRes->pEnvir->IsInTolerance = EVIIsInTolerance;
pRes->pEnvir->HandleError = EVIErrHandler;
/* new parameter space */
pRes->pParam = ObParCreate(7);
if(!pRes->pParam)
{
free(pRes->pDrivInt);
free(pRes->pEnvir);
DeleteDescriptor(pRes->pDes);
free(pRes);
return NULL;
}
ObParInit(pRes->pParam, TOLERANCE, "tolerance", 2.0, usUser);
ObParInit(pRes->pParam, ACCESS, "access", usUser, usMugger);
ObParInit(pRes->pParam, ERRORHANDLER, "errorhandler", 0.0, usUser);
ObParInit(pRes->pParam, INTERRUPT, "interrupt", eContinue, usUser);
ObParInit(pRes->pParam, UPLIMIT, "upperlimit", 300.0, usUser);
ObParInit(pRes->pParam, LOWLIMIT, "lowerlimit", 2., usUser);
ObParInit(pRes->pParam, SAFEVALUE, "safevalue", 0., usUser);
/* local initialisations */
pRes->pDriv = pDriv;
iRet = pDriv->Init(pDriv);
if(iRet >= 0)
{
*iErr = iRet;
}
/* new var log for logging values */
pRes->iLog = 1;
if(!VarlogInit(&pRes->pLog))
{
DeleteEVController(pRes);
return NULL;
}
pRes->pName = strdup(pName);
pRes->eMode = EVIdle;
pRes->iWarned = 0;
/* a terminal error gives a -1 in iRet */
if(iRet < 0)
{
DeleteEVController(pRes);
return NULL;
}
return pRes;
}
/*---------------------------------------------------------------------------*/
void DeleteEVController(void *pData)
{
pEVControl self = NULL;
self = (pEVControl)pData;
assert(self);
if(self->pDes)
{
DeleteDescriptor(self->pDes);
}
if(self->pDrivInt)
{
free(self->pDrivInt);
}
if(self->pEnvir)
{
free(self->pEnvir);
}
if(self->KillPrivate)
{
self->KillPrivate(self->pPrivate);
}
if(self->pDriv)
{
self->pDriv->Close(self->pDriv);
DeleteEVDriver(self->pDriv);
}
if(self->pName)
{
free(self->pName);
}
if(self->pParam)
{
ObParDelete(self->pParam);
}
if(self->pLog)
{
VarlogDelete(self->pLog);
}
free(self);
}
/*--------------------------------------------------------------------------*/
int EVCDrive(pEVControl self, SConnection *pCon, float fVal)
{
char pBueffel[256], pError[132];
int iRet;
assert(self);
assert(pCon);
/* Check Limits */
iRet = self->pDrivInt->CheckLimits(self, fVal, pError,131);
if(!iRet)
{
SCWrite(pCon,pError,eError);
return 0;
}
/* start executing */
iRet = StartDevice(GetExecutor(), self->pName, self->pDes,
self, pCon, fVal);
if(!iRet)
{
sprintf(pBueffel,"ERROR: Failure to start %s",self->pName);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* Wait for success */
iRet = Wait4Success(GetExecutor());
if(iRet == DEVINT)
{
return 0;
}
return 1;
}
/*--------------------------------------------------------------------------*/
int EVCGetPos(pEVControl self, SConnection *pCon, float *fPos)
{
float fVal;
assert(self);
assert(pCon);
fVal = self->pDrivInt->GetValue(self, pCon);
if(fVal < -990)
{
return 0;
}
*fPos = fVal;
return 1;
}
/*-------------------------------------------------------------------------*/
pVarLog EVCGetVarLog(pEVControl self)
{
assert(self);
return self->pLog;
}
/*---------------------------------------------------------------------------*/
EVMode EVCGetMode(pEVControl self)
{
assert(self);
return self->eMode;
}
/*--------------------------------------------------------------------------*/
int EVCSetMode(pEVControl self, EVMode eNew)
{
assert(self);
self->eMode = eNew;
return 1;
}
/*---------------------------------------------------------------------------*/
int EVCGetPar(pEVControl self, char *name, float *fVal)
{
ObPar *pPar = NULL;
assert(self);
pPar = ObParFind(self->pParam,name);
if(pPar)
{
*fVal = pPar->fVal;
return 1;
}
else
{
return 0;
}
}
/*---------------------------------------------------------------------------*/
int EVCSetPar(pEVControl self, char *name, float fVal,SConnection *pCon)
{
ObPar *pPar = NULL;
char pBueffel[512];
int iRet;
assert(self);
assert(pCon);
iRet = ObParSet(self->pParam,self->pName,name,fVal,pCon);
if(!iRet)
{
return iRet;
}
if(self->iTcl)
{
iRet = UpdateTclVariable(self->pDriv,name,fVal);
}
return iRet;
}
/*--------------------------------------------------------------------------*/
int EVCList(pEVControl self, SConnection *pCon)
{
char pBueffel[256];
float fPos;
assert(self);
assert(pCon);
sprintf(pBueffel,"Parameter listing for %s",self->pName);
SCWrite(pCon,pBueffel,eValue);
sprintf(pBueffel,"%s.%s = %f ",self->pName, "tolerance",
ObVal(self->pParam,TOLERANCE));
SCWrite(pCon,pBueffel, eValue);
sprintf(pBueffel,"%s.%s = %f",self->pName, "access",
ObVal(self->pParam,ACCESS));
SCWrite(pCon,pBueffel, eValue);
sprintf(pBueffel,"%s.%s = %f",self->pName, "ErrorHandler",
ObVal(self->pParam,ERRORHANDLER));
SCWrite(pCon,pBueffel, eValue);
sprintf(pBueffel,"%s.%s = %f",self->pName, "interrupt",
ObVal(self->pParam,INTERRUPT));
SCWrite(pCon,pBueffel, eValue);
sprintf(pBueffel,"%s.%s = %f",self->pName, "UpperLimit",
ObVal(self->pParam,UPLIMIT));
SCWrite(pCon,pBueffel, eValue);
sprintf(pBueffel,"%s.%s = %f",self->pName, "LowerLimit",
ObVal(self->pParam,LOWLIMIT));
SCWrite(pCon,pBueffel, eValue);
sprintf(pBueffel,"%s.%s = %f",self->pName, "SafeValue",
ObVal(self->pParam,SAFEVALUE));
SCWrite(pCon,pBueffel, eValue);
EVCGetPos(self,pCon,&fPos);
sprintf(pBueffel,"%s.%s = %f",self->pName, "CurrentValue",
fPos);
SCWrite(pCon,pBueffel, eValue);
sprintf(pBueffel,"%s.%s = %f",self->pName, "TargetValue",
self->fTarget);
SCWrite(pCon,pBueffel, eValue);
return 1;
}
/*---------------------------------------------------------------------------
The wrapper understands the following syntax:
EVControl : print current value
EVControl fVal : drive value
EVControl par : print parameter
EVControl par fVal : set parameter
EVControl list : lists parameters
EVControl log ... : log subcommands
EVControl send bla bla ..... : sends everything after
send to the device
---------------------------------------------------------------------------*/
int EVControlWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
pEVControl self = NULL;
char pBueffel[256], pReply[512];
double dVal;
float fPos;
int iRet;
self = (pEVControl)pData;
assert(self);
assert(pSics);
assert(pCon);
if(argc < 2) /* only value requested */
{
iRet = EVCGetPos(self,pCon,&fPos);
if(iRet)
{
sprintf(pBueffel,"%s.%s = %f",self->pName,"CurrentValue", fPos);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
return 0;
}
else
{
strtolower(argv[1]);
}
/* analyse commands */
if(strcmp(argv[1],"send") == 0) /* send to controller */
{
Arg2Text(argc-2,&argv[2],pBueffel,255);
iRet = self->pDriv->Send(self->pDriv,pBueffel,pReply, 511);
SCWrite(pCon,pReply,eValue);
return iRet;
}
else if(strcmp(argv[1],"log") == 0) /* log commands */
{
if(argc < 3)
{
SCWrite(pCon,"ERROR: insufficient number of commands for varlog",eError);
return 0;
}
iRet = VarlogWrapper(self->pLog,pCon,
argv[2],argv[3],argv[0]);
if(iRet)
{
SCSendOK(pCon);
}
return iRet;
}
else if( argc < 3) /* either parameter or drive */
{
iRet = Tcl_GetDouble(pSics->pTcl,argv[1],&dVal);
if(iRet == TCL_OK) /* float Value: drive */
{
if(!SCMatchRights(pCon,usUser))
{
return 0;
}
iRet = EVCDrive(self,pCon,(float)dVal);
if(iRet)
{
SCSendOK(pCon);
}
return iRet;
}
else if(strcmp(argv[1],"list") == 0)
{
EVCList(self,pCon);
return 1;
}
else if(strcmp(argv[1],"send") == 0) /* send to controller */
{
Arg2Text(argc-2,&argv[2],pBueffel,255);
iRet = self->pDriv->Send(self->pDriv,pBueffel,pReply, 511);
SCWrite(pCon,pReply,eValue);
return iRet;
}
else if(strcmp(argv[1],"log") == 0) /* log commands */
{
if(argc < 3)
{
SCWrite(pCon,"ERROR: insufficient number of commands for varlog",eError);
return 0;
}
return VarlogWrapper(self->pLog,pCon,
argv[2],argv[3],argv[0]);
}
else /* parameter request */
{
iRet = EVCGetPar(self,argv[1],&fPos);
if(!iRet)
{
sprintf(pBueffel,"ERROR: parameter %s NOT found",
argv[1]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
else
{
sprintf(pBueffel,"%s.%s = %f",self->pName,argv[1],fPos);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
}
}
else /* try to set parameter */
{
iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&dVal);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: %s no valid number", argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
iRet = EVCSetPar(self, argv[1],(float)dVal,pCon);
if(iRet)
{
SCSendOK(pCon);
}
return iRet;
}
return 0; /* not reached */
}
/*-------------------------------------------------------------------------
EVControlFactory implements a SICS command which creates and deletes
Controllers at run-time. Syntax:
ControlFactory new name SIM
-- creates a new controller name with a simulation driver
ControlFactory del name
-- deletes controller name
-------------------------------------------------------------------------*/
int EVControlFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
pEVControl pNew = NULL;
pEVDriver pDriv = NULL;
char pBueffel[512],pError[132];
int iRet;
CommandList *pCom = NULL;
assert(pSics);
assert(pCon);
if(argc < 3)
{
SCWrite(pCon,"ERROR: Insufficient number of arguments to EVFactory",
eError);
return 0;
}
/* check rights */
if(!SCMatchRights(pCon,usUser))
{
return 0;
}
strtolower(argv[1]);
if(strcmp(argv[1],"del") == 0) /* delete */
{
if(!pServ->pExecutor)
{
SCSendOK(pCon);
return 1;
}
if(isInRunMode(pServ->pExecutor))
{
SCWrite(pCon,"ERROR: cannot delete while running",eError);
return 0;
}
EVUnregister(FindEMON(pSics),argv[2]);
iRet = RemoveCommand(pSics,argv[2]);
if(!iRet)
{
sprintf(pBueffel,"ERROR: %s not found, NOT deleted",argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
else if(strcmp(argv[1],"new") == 0) /*make a new one */
{
/* argv[2] = name */
/* argv[3] must be type */
if(argc < 4)
{
SCWrite(pCon,"ERROR: no type specified for Environment Controller",
eError);
return 0;
}
strtolower(argv[2]);
strtolower(argv[3]);
pCom = FindCommand(pSics,argv[2]);
if(pCom)
{
sprintf(pBueffel,"ERROR: environment device %s already installed, delete first",
argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
if(strcmp(argv[3],"sim") == 0) /* SIM driver */
{
/* Create a Sim Driver */
pDriv = CreateSIMEVDriver(argc-4,&argv[4]);
if(!pDriv)
{
SCWrite(pCon,"ERROR: failed to create Environment Device driver",eError);
return 0;
}
}
else if(strcmp(argv[3],"tecs") == 0) /* TECS temperature server */
{
/* Create a driver */
pDriv = CreateTecsDriver(argc-4,&argv[4]);
if(!pDriv)
{
SCWrite(pCon,"ERROR: failed to create TECS device driver",eError);
return 0;
}
/* got a driver, initialise everything */
pNew = CreateEVController(pDriv,argv[2],&iRet);
if(!pNew)
{
SCWrite(pCon,"ERROR: failed to initialize Tecs",eError);
SCWrite(pCon,"ERROR creating Environment Controller",eError);
return 0;
}
if(!iRet)
{
SCWrite(pCon,"ERROR: problem initialising Environment controller",
eError);
pDriv->GetError(pDriv,&iRet,pError,131);
sprintf(pBueffel,"HW reported: %s",pError);
SCWrite(pCon,pBueffel,eError);
}
/* set a few parameters */
EVCSetPar(pNew,"upperlimit",300.0,pCon);
EVCSetPar(pNew,"lowerlimit",1.0,pCon);
/* install command */
iRet = AddCommand(pSics,argv[2],TecsWrapper,DeleteEVController,
pNew);
if(!iRet)
{
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[2]);
DeleteEVController((void *)pNew);
SCWrite(pCon,pBueffel,eError);
return 0;
}
EVRegisterController(FindEMON(pSics),argv[2],pNew, pCon);
SCSendOK(pCon);
return 1;
}
else if(strcmp(argv[3],"itc4") == 0) /* ITC4 driver */
{
/* Create a driver */
pDriv = CreateITC4Driver(argc-4,&argv[4]);
if(!pDriv)
{
SCWrite(pCon,"ERROR: failed to create ITC4 device driver",eError);
return 0;
}
/* got a driver, initialise everything */
pNew = CreateEVController(pDriv,argv[2],&iRet);
if(!pNew)
{
SCWrite(pCon,"ERROR creating Environment Controller",eError);
return 0;
}
if(!iRet)
{
SCWrite(pCon,"ERROR: problem initialising Environment controller",
eError);
pDriv->GetError(pDriv,&iRet,pError,131);
sprintf(pBueffel,"HW reported: %s",pError);
SCWrite(pCon,pBueffel,eError);
}
/* set a few parameters */
EVCSetPar(pNew,"upperlimit",300.0,pCon);
EVCSetPar(pNew,"lowerlimit",1.0,pCon);
/* install command */
iRet = AddCommand(pSics,argv[2],ITC4Wrapper,DeleteEVController,
pNew);
if(!iRet)
{
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[2]);
DeleteEVController((void *)pNew);
SCWrite(pCon,pBueffel,eError);
return 0;
}
EVRegisterController(FindEMON(pSics),argv[2],pNew, pCon);
SCSendOK(pCon);
return 1;
}
else if(strcmp(argv[3],"bruker") == 0) /* Bruker Magnet Controller driver */
{
/* Create a driver */
pDriv = CreateBrukerDriver(argc-4,&argv[4]);
if(!pDriv)
{
SCWrite(pCon,"ERROR: failed to create Bruker Controller device driver",eError);
return 0;
}
/* got a driver, initialise everything */
pNew = CreateEVController(pDriv,argv[2],&iRet);
if(!pNew)
{
SCWrite(pCon,"ERROR creating Environment Controller",eError);
return 0;
}
if(!iRet)
{
SCWrite(pCon,"ERROR: problem initialising Environment controller",
eError);
pDriv->GetError(pDriv,&iRet,pError,131);
sprintf(pBueffel,"HW reported: %s",pError);
SCWrite(pCon,pBueffel,eError);
}
/* set a few parameters */
EVCSetPar(pNew,"upperlimit",45.0,pCon);
EVCSetPar(pNew,"lowerlimit",0.0,pCon);
/* install command */
iRet = AddCommand(pSics,argv[2],BrukerAction,DeleteEVController,
pNew);
if(!iRet)
{
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[2]);
DeleteEVController((void *)pNew);
SCWrite(pCon,pBueffel,eError);
return 0;
}
EVRegisterController(FindEMON(pSics),argv[2],pNew, pCon);
SCSendOK(pCon);
return 1;
}
else if(strcmp(argv[3],"ltc11") == 0)
/* Neocera LTC-11 temperature controller*/
{
/* Create a driver */
pDriv = CreateLTC11Driver(argc-4,&argv[4]);
if(!pDriv)
{
SCWrite(pCon,"ERROR: failed to create LTC-11 device driver",eError);
return 0;
}
/* got a driver, initialise everything */
pNew = CreateEVController(pDriv,argv[2],&iRet);
if(!pNew)
{
SCWrite(pCon,"ERROR creating Environment Controller",eError);
return 0;
}
if(!iRet)
{
SCWrite(pCon,"ERROR: problem initialising Environment controller",
eError);
pDriv->GetError(pDriv,&iRet,pError,131);
sprintf(pBueffel,"HW reported: %s",pError);
SCWrite(pCon,pBueffel,eError);
}
/* set a few parameters */
EVCSetPar(pNew,"upperlimit",500.,pCon);
EVCSetPar(pNew,"lowerlimit",1.5,pCon);
/* install command */
iRet = AddCommand(pSics,argv[2],LTC11Action,DeleteEVController,
pNew);
if(!iRet)
{
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[2]);
DeleteEVController((void *)pNew);
SCWrite(pCon,pBueffel,eError);
return 0;
}
EVRegisterController(FindEMON(pSics),argv[2],pNew, pCon);
SCSendOK(pCon);
return 1;
}
else if(strcmp(argv[3],"tcl") == 0) /* Tcl driver */
{
/* Create a driver */
pDriv = CreateTclDriver(argc-4,&argv[4],argv[2], pCon);
if(!pDriv)
{
SCWrite(pCon,"ERROR: failed to create TCL device driver",eError);
return 0;
}
/* got a driver, initialise everything */
pNew = CreateEVController(pDriv,argv[2],&iRet);
if(!pNew)
{
SCWrite(pCon,"ERROR creating Environment Controller",eError);
DeleteEVDriver(pDriv);
return 0;
}
if(!iRet)
{
SCWrite(pCon,"ERROR: problem initialising Environment controller",
eError);
pDriv->GetError(pDriv,&iRet,pError,131);
sprintf(pBueffel,"HW reported: %s",pError);
SCWrite(pCon,pBueffel,eError);
}
/* install command */
iRet = AddCommand(pSics,argv[2],TclEnvironmentWrapper,DeleteEVController,
pNew);
if(!iRet)
{
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[2]);
DeleteEVController((void *)pNew);
SCWrite(pCon,pBueffel,eError);
return 0;
}
pNew->iTcl = 1;
/* make ev parameters available to Tcl */
UpdateTclVariable(pNew->pDriv,"tolerance",
ObVal(pNew->pParam,TOLERANCE));
UpdateTclVariable(pNew->pDriv,"upperlimit",
ObVal(pNew->pParam,UPLIMIT));
UpdateTclVariable(pNew->pDriv,"lowerlimit",
ObVal(pNew->pParam,LOWLIMIT));
/* register controller for monitoring */
EVRegisterController(FindEMON(pSics),argv[2],pNew, pCon);
SCSendOK(pCon);
return 1;
}
else if(strcmp(argv[3],"dillu") == 0) /* dillution driver */
{
/* Create a driver */
pDriv = CreateDILLUDriv(argc-4,&argv[4]);
if(!pDriv)
{
SCWrite(pCon,
"ERROR: failed to create Dillution device driver",eError);
return 0;
}
}
else if(strcmp(argv[3],"gencon") == 0) /* general controller */
{
/* Create a driver */
pDriv = MakeControllerEnvironmentDriver(argc-4,&argv[4]);
if(!pDriv)
{
SCWrite(pCon,
"ERROR: failed to create Controller Environment driver",
eError);
return 0;
}
}
else if(strcmp(argv[3],"euro") == 0) /* dillution driver */
{
/* Create a driver */
pDriv = CreateEURODriv(argc-4,&argv[4]);
if(!pDriv)
{
SCWrite(pCon,
"ERROR: failed to create Eurotherm device driver",eError);
return 0;
}
}
else if(strcmp(argv[3],"el755") == 0) /* EL755 magnet driver */
{
/* Create a driver */
pDriv = CreateEL755Driv(argc-4,&argv[4]);
if(!pDriv)
{
SCWrite(pCon,
"ERROR: failed to create EL755 device driver",eError);
return 0;
}
}
else
{
sprintf(pBueffel,"ERROR: %s not recognized as a valid driver type",
argv[3]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* got a driver, initialise everything */
pNew = CreateEVController(pDriv,argv[2],&iRet);
if(!pNew)
{
SCWrite(pCon,"ERROR creating Environment Controller",eError);
return 0;
}
if(!iRet)
{
SCWrite(pCon,"ERROR: problem initialising Environment controller",
eError);
pDriv->GetError(pDriv,&iRet,pError,131);
sprintf(pBueffel,"HW reported: %s",pError);
SCWrite(pCon,pBueffel,eError);
}
/* set a few parameters */
if(strcmp(argv[3],"euro") == 0)
{
EVCSetPar(pNew,"upperlimit",750.0,pCon);
EVCSetPar(pNew,"lowerlimit",15.0,pCon);
}
else if(strcmp(argv[3],"el755") == 0)
{
EVCSetPar(pNew,"upperlimit",10.,pCon);
EVCSetPar(pNew,"lowerlimit",-10.,pCon);
}
else
{
EVCSetPar(pNew,"upperlimit",4.0,pCon);
EVCSetPar(pNew,"lowerlimit",0.05,pCon);
}
/* install command */
iRet = AddCommand(pSics,argv[2],EVControlWrapper,DeleteEVController,
pNew);
if(!iRet)
{
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[2]);
DeleteEVController((void *)pNew);
SCWrite(pCon,pBueffel,eError);
return 0;
}
EVRegisterController(FindEMON(pSics),argv[2],pNew, pCon);
SCSendOK(pCon);
return 1;
}
SCWrite(pCon,"ERROR: command not understood",eError);
return 0;
}