Treat Tcl procs prefixed with imot_, hdb_ and get_ specially.

hdb_, Parameter will be added to hdb tree.
imot_, Motor interface function, eg run, status.
get_, Tcl code will be evaluated when "mot list" is called.
Add debug info.
This commit is contained in:
Ferdi Franceschini
2013-04-20 18:28:28 +10:00
parent b98ff24528
commit a5c097cedc
4 changed files with 498 additions and 408 deletions

View File

@ -153,6 +153,7 @@ GHTTP_LIBS = $(LIB_HTTP)
OBJ= site_ansto.o anstoutil.o\
ansto_sctdriveadapter.o\
ansto_tclmotdriv.o\
sctemonadapter.o\
motor_asim.o motor_dmc2280.o\
lh45.o lh45driv.o \

View File

@ -19,9 +19,18 @@
facilitate error handling, a motor parameter errorcode is available to
store errors between invocations.
Author: Jing Chen, Nov 2012
copyright: see file COPYRIGHT
Author: Mark Koennecke, December 2005
ANSTO MODIFICATIONS:
Jing Chen, Nov 2012:
Support extra parameters as calls to Tcl code.
Ferdi Franceschini April 2013:
Use prefixes imot_, hdb_, and get_ to tell driver how to handle different
types of functions. Added debug info support.
--------------------------------------------------------------------------*/
#include <stdlib.h>
@ -32,7 +41,7 @@
#include "modriv.h"
#include "lld.h"
#include "stringdict.h"
#include "tclmotdriv.h"
#include "ansto_tclmotdriv.h"
#define FUNCNOTFOUND -11000
#define TCLERROR -11001
@ -44,10 +53,16 @@
#define LONG_NAME "long_name"
#define ERRORCODE "errorcode"
void logTclCall(TCLDriv *pDriv, char *fn, char *script) {
char msg[512];
snprintf(msg, 511, "tclmot %s.%s -> %s\n", pDriv->motName, fn, script);
SICSLogWrite(msg, eLog);
}
/*----------------------------------------------------------------------------*/
static int buildStandardCommandPart(TCLDriv * pDriv, char *command,
char *tclCommand, int commandLen){
char *tclCommand, int commandLen)
{
char tclFunc[132];
int status;
@ -55,14 +70,15 @@ static int buildStandardCommandPart(TCLDriv *pDriv, char *command,
if (status != 1) {
return 0;
}
//snprintf(tclCommand,commandLen,"%s %s ", tclFunc, pDriv->motName);
snprintf(tclCommand,commandLen,"%s", tclFunc);
snprintf(tclCommand,commandLen,"%s %s ", tclFunc, pDriv->motName);
//snprintf(tclCommand, commandLen, "%s", tclFunc);
return 1;
}
/*----------------------------------------------------------------------------*/
static int GetTclPos(void *self, float *fPos){
static int GetTclPos(void *self, float *fPos)
{
TCLDriv *pDriv;
int status;
const char *result = NULL;
@ -79,6 +95,9 @@ static int buildStandardCommandPart(TCLDriv *pDriv, char *command,
return HWFault;
}
if (pDriv->debug)
logTclCall(pDriv, "getpos", tclCommand);
status = Tcl_Eval(pServ->pSics->pTcl, tclCommand);
result = Tcl_GetStringResult(pServ->pSics->pTcl);
free(tclCommand);
@ -94,8 +113,10 @@ static int buildStandardCommandPart(TCLDriv *pDriv, char *command,
sscanf(result, "%f", fPos);
return OKOK;
}
/*----------------------------------------------------------------------------*/
static int TclRun(void *self, float fVal) {
static int TclRun(void *self, float fVal)
{
TCLDriv *pDriv;
char num[80];
int status;
@ -115,6 +136,9 @@ static int buildStandardCommandPart(TCLDriv *pDriv, char *command,
snprintf(num, 79, "%f", fVal);
strncat(tclCommand, num, 1023 - strlen(tclCommand));
if (pDriv->debug)
logTclCall(pDriv, "run", tclCommand);
status = Tcl_Eval(pServ->pSics->pTcl, tclCommand);
result = Tcl_GetStringResult(pServ->pSics->pTcl);
free(tclCommand);
@ -130,12 +154,15 @@ static int buildStandardCommandPart(TCLDriv *pDriv, char *command,
sscanf(result, "%d", &status);
return status;
}
/*-------------------------------------------------------------------------*/
static int evaluateInternalErrors(TCLDriv * pDriv, int *iCode,
char *error, int iErrLen){
char *error, int iErrLen)
{
switch (pDriv->errorCode) {
case FUNCNOTFOUND:
strncpy(error,"Config Error: Tcl function for driver not found",iErrLen);
strncpy(error, "Config Error: Tcl function for driver not found",
iErrLen);
*iCode = pDriv->errorCode;
return 1;
break;
@ -155,8 +182,10 @@ static int evaluateInternalErrors(TCLDriv *pDriv, int *iCode,
}
return 0;
}
/*--------------------------------------------------------------------------*/
static void TclGetError(void *self, int *iCode, char *error, int iErrLen){
static void TclGetError(void *self, int *iCode, char *error, int iErrLen)
{
TCLDriv *pDriv;
int status = 1;
const char *result = NULL;
@ -176,6 +205,9 @@ static int evaluateInternalErrors(TCLDriv *pDriv, int *iCode,
}
if (status != 0) {
if (pDriv->debug)
logTclCall(pDriv, "geterror", tclCommand);
status = Tcl_Eval(pServ->pSics->pTcl, tclCommand);
result = Tcl_GetStringResult(pServ->pSics->pTcl);
if (result == NULL) {
@ -196,7 +228,8 @@ static int evaluateInternalErrors(TCLDriv *pDriv, int *iCode,
}
/*---------------------------------------------------------------------------*/
static int TclTryAndFixIt(void *self, int iError, float fNew){
static int TclTryAndFixIt(void *self, int iError, float fNew)
{
TCLDriv *pDriv;
char num[80];
int status;
@ -215,6 +248,9 @@ static int evaluateInternalErrors(TCLDriv *pDriv, int *iCode,
snprintf(num, 79, "%d %f", pDriv->errorCode, fNew);
strncat(tclCommand, num, 1023 - strlen(tclCommand));
if (pDriv->debug)
logTclCall(pDriv, "fixit", tclCommand);
status = Tcl_Eval(pServ->pSics->pTcl, tclCommand);
result = Tcl_GetStringResult(pServ->pSics->pTcl);
if (result == NULL) {
@ -253,6 +289,9 @@ static int evaluateInternalErrors(TCLDriv *pDriv, int *iCode,
return HWFault;
}
if (pDriv->debug)
logTclCall(pDriv, "halt", tclCommand);
status = Tcl_Eval(pServ->pSics->pTcl, tclCommand);
result = Tcl_GetStringResult(pServ->pSics->pTcl);
if (result == NULL) {
@ -290,6 +329,9 @@ static int evaluateInternalErrors(TCLDriv *pDriv, int *iCode,
return HWFault;
}
if (pDriv->debug)
logTclCall(pDriv, "status", tclCommand);
status = Tcl_Eval(pServ->pSics->pTcl, tclCommand);
result = Tcl_GetStringResult(pServ->pSics->pTcl);
if (result == NULL) {
@ -309,10 +351,12 @@ static int evaluateInternalErrors(TCLDriv *pDriv, int *iCode,
}
/*-----------------------------------------------------------------------*/
static int TclSetPar(void *self, SConnection *pCon, char *name, float newValue){
static int TclSetPar(void *self, SConnection * pCon, char *name,
float newValue)
{
/*TODO Skip functions in driveable interface ie "run" etc. */
int status;
const char *result = NULL;
char *result = NULL, pBuffer[512];
TCLDriv *pDriv = (TCLDriv *) self;
@ -328,9 +372,12 @@ static int TclSetPar(void *self, SConnection *pCon, char *name, float newValue){
} else if (strcmp(name, ERRORCODE) == 0) {
pDriv->errorCode = (int) newValue;
return 1;
} else if (strcmp(name, LONG_NAME) == 0) {
strncpy(pDriv->long_name, &newValue, 255);
} else if (strcmp(name, "debug") == 0) {
pDriv->debug = (int) newValue;
return 1;
/* } else if (strcmp(name, LONG_NAME) == 0) {
strncpy(pDriv->long_name, &newValue, 255);
return 1;*/
} else {
char *tclCommand = (char *) calloc(1024, sizeof(char));
if (StringDictExists(pDriv->mappings, name)) {
@ -341,6 +388,10 @@ static int TclSetPar(void *self, SConnection *pCon, char *name, float newValue){
}
char *tclCommandPara = (char *) calloc(1024, sizeof(char));
sprintf(tclCommandPara, "%s %f", tclCommand, newValue);
if (pDriv->debug)
logTclCall(pDriv, name, tclCommand);
status = Tcl_Eval(pServ->pSics->pTcl, tclCommandPara);
result = Tcl_GetStringResult(pServ->pSics->pTcl);
if (result == NULL) {
@ -355,6 +406,9 @@ static int TclSetPar(void *self, SConnection *pCon, char *name, float newValue){
free(tclCommand);
free(tclCommandPara);;
return HWFault;
} else {
snprintf(pBuffer, 511, "%s.%s = %s", pDriv->motName, name, result);
SCWrite(pCon, pBuffer, eValue);
}
free(tclCommand);
free(tclCommandPara);;
@ -368,49 +422,9 @@ static int TclSetPar(void *self, SConnection *pCon, char *name, float newValue){
}
}
static int TclListPar(void *self, char *motorname, SConnection *pCon) {
SDE sVal;
int iRet;
char pBueffel[512];
char *funcText[] = {"getpos",
"run",
"status",
"halt",
"geterror",
"fixit",
NULL};
TCLDriv *pDriv = (TCLDriv *)self;
iRet = LLDnodePtr2First(pDriv->mappings->iList);
while(iRet != 0){
LLDnodeDataTo(pDriv->mappings->iList, &sVal);
int count=0, flag=0;
while(funcText[count]!=NULL && flag==0) {
if(strcmp(sVal.name,funcText[count]) == 0)
flag = 1;
count++;
}
if(flag==0) {
int ret;
float value;
ret = TclGetPar(self, sVal.name, &value);
if (ret != OKOK) {
return ret;
} else {
snprintf(pBueffel,511,"%s.%s = %f",motorname,sVal.name,value);
SCWrite(pCon,pBueffel,eValue);
}
}
iRet = LLDnodePtr2Next(pDriv->mappings->iList);
}
return OKOK;
}
/*-----------------------------------------------------------------------*/
int TclGetPar(void *self, char *name, float *value) {
int TclGetPar(void *self, char *name, float *value)
{
int status;
const char *result = NULL;
@ -428,6 +442,9 @@ int TclGetPar(void *self, char *name, float *value) {
} else if (strcmp(name, HARDLOWERLIM) == 0) {
*value = (float) pDriv->fLower;
return OKOK;
} else if (strcmp(name, "debug") == 0) {
*value = (float) pDriv->debug;
return OKOK;
} else {
char *tclCommand = (char *) calloc(1024, sizeof(char));
if (StringDictExists(pDriv->mappings, name)) {
@ -436,6 +453,9 @@ int TclGetPar(void *self, char *name, float *value) {
free(tclCommand);
return HWFault;
}
if (pDriv->debug)
logTclCall(pDriv, name, tclCommand);
status = Tcl_Eval(pServ->pSics->pTcl, tclCommand);
result = Tcl_GetStringResult(pServ->pSics->pTcl);
if (result == NULL) {
@ -461,6 +481,57 @@ int TclGetPar(void *self, char *name, float *value) {
return OKOK;
}
}
/*
* Functions which include hdb_, imot_, and get_ are treated specially.
* hdb_, Parameter will be added to hdb tree.
* imot_, Motor interface function, eg run, status.
* get_, Tcl code will be evaluated when "mot list" is called.
* WARNING: Parameters prefixed with hdb_ will be executed when any of the
* parameters in the hdb tree are updated, for instance if the
* softzero is changed.
*/
void TclListPar(void *self, char *motorname, SConnection * pCon)
{
char pBueffel[512];
char motParVal[256];
float value;
const char *motPar=NULL;
TCLDriv *pDriv = (TCLDriv *) self;
int pos = 0, imot;
snprintf(pBueffel, 511, "%s.debug = %d", motorname, pDriv->debug);
SCWrite(pCon, pBueffel, eValue);
while ( (motPar = StringDictGetNext(pDriv->mappings,motParVal,256)) != NULL ) {
imot = 0;
pBueffel[0] = '\0';
/* sicshipadaba sets motorname="test" when constructing hdb tree */
if (strcmp(motorname, "test.") == 0 && strstr(motParVal, "hdb_") == NULL)
continue;
if (strstr(motParVal, "imot_"))
imot = 1;
if (imot && !pDriv->debug)
continue;
pos = snprintf(pBueffel, 511, "%s.%s", motorname, motPar);
if (pDriv->debug)
pos += snprintf(&pBueffel[pos], 511, "->[%s]", motParVal);
if (strstr(motParVal, "get_")) {
TclGetPar(self, (char *)motPar, &value);
snprintf(&pBueffel[pos], 511, " = %f", value);
} else if (imot)
snprintf(&pBueffel[pos], 511, " (imot)");
else
snprintf(&pBueffel[pos], 511, " (command)");
if (pBueffel[0] != '\0')
SCWrite(pCon, pBueffel, eValue);
}
}
/*---------------------------------------------------------------------------*/
void KillTCL(void *pData)
{
@ -472,51 +543,34 @@ int TclGetPar(void *self, char *name, float *value) {
return;
}
/*-------------------------------------------------------------------------*/
static int assignMappings(TCLDriv *pDriv, SConnection *pCon, char *arrayName){
static int assignMappings(TCLDriv * pDriv, SConnection * pCon,
char *arrayName)
{
const char *funcName = NULL;
char *funcText[] = { "getpos",
"run",
"status",
"halt",
"geterror",
"fixit",
NULL
};
char error[256];
int count = 0;
if (*arrayName==NULL) {
return OKOK;
} else {
unsigned char ps=0;
char *pch;
char *funcName = (char *)calloc(1024, sizeof(char));
char **argv;
int i, code, argc;
pch = strtok(arrayName, "{}");
while (pch != NULL) {
int c=0;
while(pch[c]==' ' && c<strlen(pch)) c++;
char *newStr = (char *)calloc(strlen(pch)-c+1, sizeof(char));
if(c==strlen(pch)) {
*newStr = NULL;
} else {
int ind=0;
while(c<strlen(pch)) {
newStr[ind] = pch[c];
c++;
ind++;
}
}
if (ps%2==0){
if (*newStr==NULL) {
free(newStr);
free(funcName);
return OKOK;
} else {
strcpy(funcName, newStr);
ps++;
}
} else {
StringDictAddPair(pDriv->mappings,funcName, newStr);
ps = 0;
}
free(newStr);
pch = strtok (NULL, "{}");
}
free(funcName);
code = Tcl_SplitList(pServ->pSics->pTcl, arrayName, &argc, &argv);
for (i=0; i < argc; i += 2) {
StringDictAddPair(pDriv->mappings, argv[i], (char *) argv[i+1]);
}
Tcl_Free((char *) argv);
return 1;
}
/*--------------------------------------------------------------------------*/
MotorDriver *CreateTclMotDriv(SConnection * pCon, int argc, char *argv[])
{
@ -525,7 +579,8 @@ static int assignMappings(TCLDriv *pDriv, SConnection *pCon, char *arrayName){
assert(pCon);
if (argc < 4) {
SCWrite(pCon,"ERROR: not enough arguments to initilaize Tcl-driver",eError);
SCWrite(pCon, "ERROR: not enough arguments to initilaize Tcl-driver",
eError);
return NULL;
}
@ -535,6 +590,7 @@ static int assignMappings(TCLDriv *pDriv, SConnection *pCon, char *arrayName){
return NULL;
}
memset(pDriv, 0, sizeof(TCLDriv));
pDriv->debug = 0;
pDriv->mappings = CreateStringDict();
if (pDriv->mappings == NULL) {
SCWrite(pCon, "Error allocating memory in TclMotor", eError);
@ -562,13 +618,3 @@ static int assignMappings(TCLDriv *pDriv, SConnection *pCon, char *arrayName){
return (MotorDriver *) pDriv;
}

View File

@ -0,0 +1,43 @@
/*---------------------------------------------------------------------------
This is a motor driver which is implemented in Tcl. This means
this code is only a wrapper which calls Tcl functions to do the
actual work.
copyright: see file COPYRIGHT
Mark Koennecke, December 2005
--------------------------------------------------------------------------*/
#ifndef TCLMOTDRIV
#define TCLMOTDRIV
#include "stringdict.h"
typedef struct ___TclDriv {
/* general motor driver interface
fields. REQUIRED!
*/
float fUpper; /* upper limit */
float fLower; /* lower limit */
char *name;
int (*GetPosition) (void *self, float *fPos);
int (*RunTo) (void *self, float fNewVal);
int (*GetStatus) (void *self);
void (*GetError) (void *self, int *iCode, char *buffer, int iBufLen);
int (*TryAndFixIt) (void *self, int iError, float fNew);
int (*Halt) (void *self);
int (*GetDriverPar) (void *self, char *name, float *value);
int (*SetDriverPar) (void *self, SConnection * pCon,
char *name, float newValue);
void (*ListDriverPar) (void *self, char *motorName, SConnection * pCon);
void (*KillPrivate) (void *self);
/* Tcl specific fields */
pStringDict mappings;
int debug;
int errorCode;
char tclError[1024];
char motName[132];
} TCLDriv;
MotorDriver *CreateTclMotDriv(SConnection * pCon, int argc, char *argv[]);
#endif

View File

@ -22,7 +22,7 @@ SOBJ = alias.o anticollider.o arrayutil.o ascon.o asyncprotocol.o asyncqueue.o a
sicvar.o sig_die.o simchop.o simev.o simidx.o simindex.o sinfox.o singlebi.o singlediff.o singlenb.o singlebinb.o singletas.o singlex.o splitter.o s_rnge.o statemon.o \
statistics.o statusfile.o status.o stdscan.o stptok.o stringdict.o strlutil.o strrepl.o \
syncedprot.o synchronize.o tasdrive.o task.o tasscanub.o tasublib.o tasub.o tcldrivable.o \
tclev.o tclintimpl.o tclmotdriv.o telnet.o testprot.o token.o trace.o trigd.o trim.o ubcalc.o \
tclev.o tclintimpl.o telnet.o testprot.o token.o trace.o trigd.o trim.o ubcalc.o \
ubfour.o udpquieck.o uselect.o userscan.o uubuffer.o varlog.o vector.o velosec.o wwildcard.o \
xytable.o