- SECoP protocol for scriptcontext
This commit is contained in:
10
ascon.c
10
ascon.c
@ -150,9 +150,11 @@ static void AsconConnect(Ascon * a)
|
|||||||
ret = CreateSocketAdress(&adr, a->hostport, port);
|
ret = CreateSocketAdress(&adr, a->hostport, port);
|
||||||
*colon = ':';
|
*colon = ':';
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
|
a->ip = 0;
|
||||||
AsconError(a, "bad host specification", 0);
|
AsconError(a, "bad host specification", 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
a->ip = adr.sin_addr.s_addr;
|
||||||
oldopts = fcntl(a->fd, F_GETFL, 0);
|
oldopts = fcntl(a->fd, F_GETFL, 0);
|
||||||
fcntl(a->fd, F_SETFL, oldopts | O_NONBLOCK);
|
fcntl(a->fd, F_SETFL, oldopts | O_NONBLOCK);
|
||||||
ret =
|
ret =
|
||||||
@ -853,6 +855,14 @@ char *AsconHostport(Ascon *a)
|
|||||||
return a->hostport;
|
return a->hostport;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned long AsconIP(Ascon *a)
|
||||||
|
{
|
||||||
|
if (a==NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return a->ip;
|
||||||
|
}
|
||||||
|
|
||||||
double AsconGetSetTimeout(Ascon *a, double timeout, int setmode) {
|
double AsconGetSetTimeout(Ascon *a, double timeout, int setmode) {
|
||||||
if (setmode) {
|
if (setmode) {
|
||||||
a->timeout = timeout;
|
a->timeout = timeout;
|
||||||
|
7
ascon.h
7
ascon.h
@ -109,6 +109,13 @@ int AsconLastState(Ascon *a);
|
|||||||
*/
|
*/
|
||||||
char *AsconHostport(Ascon *a);
|
char *AsconHostport(Ascon *a);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief return IP address
|
||||||
|
* \param a The Ascon to query
|
||||||
|
* \return the IP address
|
||||||
|
*/
|
||||||
|
unsigned long AsconIP(Ascon *a);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief set or get timeout
|
* \brief set or get timeout
|
||||||
* \param a the Ascon
|
* \param a the Ascon
|
||||||
|
1
ascon.i
1
ascon.i
@ -65,6 +65,7 @@ struct Ascon {
|
|||||||
char *sendTerminator; /**< terminator for sending messages */
|
char *sendTerminator; /**< terminator for sending messages */
|
||||||
char *replyTerminator; /**< (std) terminator list for reply. NULL is the special case CR, LF or CR/LF */
|
char *replyTerminator; /**< (std) terminator list for reply. NULL is the special case CR, LF or CR/LF */
|
||||||
char *hostport; /**< host:port to connect */
|
char *hostport; /**< host:port to connect */
|
||||||
|
in_addr_t ip; /**< the ip address */
|
||||||
pDynString errmsg; /**< error message */
|
pDynString errmsg; /**< error message */
|
||||||
double start; /**< unix time when read was started */
|
double start; /**< unix time when read was started */
|
||||||
int noResponse; /**< no response expected */
|
int noResponse; /**< no response expected */
|
||||||
|
66
binprot.c
66
binprot.c
@ -72,9 +72,12 @@
|
|||||||
* chksum-crc: simple 8bit checksum
|
* chksum-crc: simple 8bit checksum
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define SIMULATE_ERROR 0
|
||||||
|
static int simulate_error = 0;
|
||||||
|
|
||||||
typedef enum {intType, hexType, floatType, strType,
|
typedef enum {intType, hexType, floatType, strType,
|
||||||
skipType, codeType, checkType, crcType,
|
skipType, codeType, checkType, crcType,
|
||||||
dumpType, endType, errorType} BinDataType; // items on this line stay at end
|
dumpType, endType, errorType} BinDataType; /* items on this line stay at end */
|
||||||
|
|
||||||
typedef enum {modbusCrc, kellerCrc, rsportCrc, syconCrc, chksumCrc} CrcAlgorithm;
|
typedef enum {modbusCrc, kellerCrc, rsportCrc, syconCrc, chksumCrc} CrcAlgorithm;
|
||||||
|
|
||||||
@ -83,7 +86,8 @@ typedef struct {
|
|||||||
CrcAlgorithm algo;
|
CrcAlgorithm algo;
|
||||||
int crcStart;
|
int crcStart;
|
||||||
pDynString inp;
|
pDynString inp;
|
||||||
char *nextFmt; // position of next format token
|
char *nextFmt; /* position of next format token */
|
||||||
|
char *readFmt; /* position of first read format */
|
||||||
pDynString result;
|
pDynString result;
|
||||||
int expectedChars;
|
int expectedChars;
|
||||||
BinDataType type;
|
BinDataType type;
|
||||||
@ -94,6 +98,8 @@ typedef struct {
|
|||||||
int syconState;
|
int syconState;
|
||||||
unsigned char chksum;
|
unsigned char chksum;
|
||||||
pDynString data;
|
pDynString data;
|
||||||
|
int try_again_count;
|
||||||
|
int try_again_max;
|
||||||
} BinPrivate;
|
} BinPrivate;
|
||||||
|
|
||||||
#define MAXDUMP 999
|
#define MAXDUMP 999
|
||||||
@ -383,6 +389,15 @@ void BinShuffle(char *input, int order) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
void BinResetWrite(Ascon *a) {
|
||||||
|
BinPrivate *p = a->private;
|
||||||
|
p->nextFmt = p->readFmt;
|
||||||
|
a->wrPos = 0;
|
||||||
|
a->lineCount = 0;
|
||||||
|
a->state = AsconWriting;
|
||||||
|
}
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
int BinHandler(Ascon *a) {
|
int BinHandler(Ascon *a) {
|
||||||
int res;
|
int res;
|
||||||
@ -408,6 +423,7 @@ int BinHandler(Ascon *a) {
|
|||||||
/* exchange buffers */
|
/* exchange buffers */
|
||||||
dyn = p->inp;
|
dyn = p->inp;
|
||||||
p->inp = a->wrBuffer;
|
p->inp = a->wrBuffer;
|
||||||
|
p->try_again_count = p->try_again_max;
|
||||||
a->wrBuffer = dyn;
|
a->wrBuffer = dyn;
|
||||||
DynStringClear(dyn);
|
DynStringClear(dyn);
|
||||||
str = GetCharArray(p->inp);
|
str = GetCharArray(p->inp);
|
||||||
@ -530,7 +546,8 @@ int BinHandler(Ascon *a) {
|
|||||||
BinToSycon(dyn);
|
BinToSycon(dyn);
|
||||||
}
|
}
|
||||||
|
|
||||||
p->nextFmt = str + pos;
|
p->readFmt = str + pos;
|
||||||
|
p->nextFmt = p->readFmt;
|
||||||
p->type = hexType; /* initialize to anything < dumpType */
|
p->type = hexType; /* initialize to anything < dumpType */
|
||||||
do {
|
do {
|
||||||
res = BinReadItem(a);
|
res = BinReadItem(a);
|
||||||
@ -540,15 +557,11 @@ int BinHandler(Ascon *a) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} while (res == 1);
|
} while (res == 1);
|
||||||
p->nextFmt = str + pos;
|
BinResetWrite(a);
|
||||||
a->wrPos = 0;
|
|
||||||
if (GetDynStringLength(a->wrBuffer) == 0) {
|
if (GetDynStringLength(a->wrBuffer) == 0) {
|
||||||
/* prevent to swallow "garbage" */
|
/* prevent to swallow "garbage" */
|
||||||
a->state = AsconWriteDone;
|
a->state = AsconWriteDone;
|
||||||
} else {
|
|
||||||
a->state = AsconWriting;
|
|
||||||
}
|
}
|
||||||
a->lineCount = 0;
|
|
||||||
return 1;
|
return 1;
|
||||||
case AsconReadStart:
|
case AsconReadStart:
|
||||||
DynStringClear(p->result);
|
DynStringClear(p->result);
|
||||||
@ -558,10 +571,16 @@ int BinHandler(Ascon *a) {
|
|||||||
break;
|
break;
|
||||||
case AsconReading:
|
case AsconReading:
|
||||||
res = AsconBaseHandler(a);
|
res = AsconBaseHandler(a);
|
||||||
|
if (a->state == AsconTimeout && p->try_again_count > 0) {
|
||||||
|
p->try_again_count--;
|
||||||
|
DynStringCopy(a->errmsg, "timeout");
|
||||||
|
BinResetWrite(a);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
if (GetDynStringLength(a->rdBuffer) == 0) {
|
if (GetDynStringLength(a->rdBuffer) == 0) {
|
||||||
/* wait for the first byte - or timeout */
|
/* wait for the first byte - or timeout */
|
||||||
return res;
|
return 0;
|
||||||
}
|
}
|
||||||
if (p->type >= dumpType) {
|
if (p->type >= dumpType) {
|
||||||
l = GetDynStringLength(a->rdBuffer);
|
l = GetDynStringLength(a->rdBuffer);
|
||||||
@ -578,15 +597,23 @@ int BinHandler(Ascon *a) {
|
|||||||
DynStringConcat(a->errmsg, GetCharArray(p->result));
|
DynStringConcat(a->errmsg, GetCharArray(p->result));
|
||||||
a->state = AsconFailed;
|
a->state = AsconFailed;
|
||||||
} else {
|
} else {
|
||||||
|
if (p->try_again_count != p->try_again_max) {
|
||||||
|
Log(INFO, "com", "sock0:recovered from (%s) after: %s", GetCharArray(a->errmsg), GetCharArray(p->inp));
|
||||||
|
}
|
||||||
a->state = AsconReadDone;
|
a->state = AsconReadDone;
|
||||||
}
|
}
|
||||||
/* exchange buffers */
|
/* exchange buffers */
|
||||||
dyn = a->rdBuffer;
|
dyn = a->rdBuffer;
|
||||||
a->rdBuffer = p->result;
|
a->rdBuffer = p->result;
|
||||||
p->result = dyn;
|
p->result = dyn;
|
||||||
|
if (a->state == AsconFailed && p->try_again_count > 0) {
|
||||||
|
p->try_again_count--;
|
||||||
|
BinResetWrite(a);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return res;
|
return 0;
|
||||||
}
|
}
|
||||||
if (p->crcAlgorithm == syconCrc) {
|
if (p->crcAlgorithm == syconCrc) {
|
||||||
switch (p->syconState) {
|
switch (p->syconState) {
|
||||||
@ -745,13 +772,23 @@ int BinHandler(Ascon *a) {
|
|||||||
p->expectedChars--;
|
p->expectedChars--;
|
||||||
if ((unsigned char)a->lastChar != p->iValue) {
|
if ((unsigned char)a->lastChar != p->iValue) {
|
||||||
i = GetDynStringLength(a->rdBuffer) - 1;
|
i = GetDynStringLength(a->rdBuffer) - 1;
|
||||||
snprintf(item, sizeof item, "BINERR: response[%d]==%2.2x != %2.2x ", i, (unsigned char)a->lastChar, (unsigned char)p->iValue);
|
snprintf(item, sizeof item, "BINERR: [%d]==%2.2x != %2.2x ", i, (unsigned char)a->lastChar, (unsigned char)p->iValue);
|
||||||
DynStringCopy(a->errmsg, item);
|
DynStringCopy(a->errmsg, item);
|
||||||
p->type = errorType;
|
p->type = errorType;
|
||||||
p->dumpFrom = 0;
|
p->dumpFrom = 0;
|
||||||
/* skip to end */
|
/* skip to end */
|
||||||
p->nextFmt = "";
|
p->nextFmt = "";
|
||||||
}
|
}
|
||||||
|
#if SIMULATE_ERROR > 0
|
||||||
|
if (p->try_again_max > 0 && simulate_error++ > SIMULATE_ERROR) {
|
||||||
|
DynStringCopy(a->errmsg, "simulate ");
|
||||||
|
p->type = errorType;
|
||||||
|
p->dumpFrom = 0;
|
||||||
|
/* skip to end */
|
||||||
|
p->nextFmt = "";
|
||||||
|
simulate_error = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (p->expectedChars <= 0) {
|
if (p->expectedChars <= 0) {
|
||||||
BinReadItem(a);
|
BinReadItem(a);
|
||||||
@ -773,6 +810,7 @@ static int BinInit(Ascon * a, SConnection * con, int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
BinPrivate *p;
|
BinPrivate *p;
|
||||||
|
|
||||||
|
/* args: 2 <protocol>, 3 <timeout>, 4 <try_again_max>
|
||||||
/* argv[2] may be modbus-crc (default), keller-crc, rsport-crc or sycon-crc */
|
/* argv[2] may be modbus-crc (default), keller-crc, rsport-crc or sycon-crc */
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
@ -807,6 +845,12 @@ static int BinInit(Ascon * a, SConnection * con, int argc, char *argv[])
|
|||||||
} else {
|
} else {
|
||||||
a->timeout = 2.0; /* sec */
|
a->timeout = 2.0; /* sec */
|
||||||
}
|
}
|
||||||
|
if (argc > 4) {
|
||||||
|
p->try_again_max = atoi(argv[4]);
|
||||||
|
} else {
|
||||||
|
p->try_again_max = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
devser.c
4
devser.c
@ -580,6 +580,10 @@ char *DevHostport(DevSer *devser) {
|
|||||||
return AsconHostport(devser->ascon);
|
return AsconHostport(devser->ascon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned long DevIP(DevSer *devser) {
|
||||||
|
return AsconIP(devser->ascon);
|
||||||
|
}
|
||||||
|
|
||||||
char *DevStatus(DevSer *devser) {
|
char *DevStatus(DevSer *devser) {
|
||||||
char *str, *pos;
|
char *str, *pos;
|
||||||
static char buf[64];
|
static char buf[64];
|
||||||
|
7
devser.h
7
devser.h
@ -203,6 +203,13 @@ void DevAsconStatistics(DevSer *self, double *avg,
|
|||||||
*/
|
*/
|
||||||
char *DevHostport(DevSer *devser);
|
char *DevHostport(DevSer *devser);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief return IP address
|
||||||
|
* \param a The device serializer to query
|
||||||
|
* \return the IP address
|
||||||
|
*/
|
||||||
|
unsigned long DevIP(DevSer *devser);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief return status of device server ("offline", "unconnected", "")
|
* \brief return status of device server ("offline", "unconnected", "")
|
||||||
* \param devser The device serializer to query
|
* \param devser The device serializer to query
|
||||||
|
8
drive.c
8
drive.c
@ -121,17 +121,17 @@ int Drive(SConnection * pCon, SicsInterp * pInter, char *name, float fNew)
|
|||||||
if (iRet == DEVINT) {
|
if (iRet == DEVINT) {
|
||||||
if (SCGetInterrupt(pCon) == eAbortOperation) {
|
if (SCGetInterrupt(pCon) == eAbortOperation) {
|
||||||
SCSetInterrupt(pCon, eContinue);
|
SCSetInterrupt(pCon, eContinue);
|
||||||
snprintf(pBueffel, 511, "Driving %s aborted at %9.3f", name, fPos);
|
snprintf(pBueffel, 511, "Driving %s aborted at %.6g", name, fPos);
|
||||||
SCWrite(pCon, pBueffel, eError);
|
SCWrite(pCon, pBueffel, eError);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} else if (iRet == DEVDONE) {
|
} else if (iRet == DEVDONE) {
|
||||||
snprintf(pBueffel, 511, "Driving %s to %9.3f done", name, fPos);
|
snprintf(pBueffel, 511, "Driving %s to %.6g done", name, fPos);
|
||||||
SCWrite(pCon, pBueffel, eValue);
|
SCWrite(pCon, pBueffel, eValue);
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
snprintf(pBueffel, 511,
|
snprintf(pBueffel, 511,
|
||||||
"Driving %s finished with problems, position: %9.3f", name,
|
"Driving %s finished with problems, position: %.6g", name,
|
||||||
fPos);
|
fPos);
|
||||||
SCWrite(pCon, pBueffel, eValue);
|
SCWrite(pCon, pBueffel, eValue);
|
||||||
return 1;
|
return 1;
|
||||||
@ -341,7 +341,7 @@ int DriveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
|
|
||||||
/* print positions */
|
/* print positions */
|
||||||
for (i = 1; i < argc; i += 2) {
|
for (i = 1; i < argc; i += 2) {
|
||||||
snprintf(pBueffel,511, "New %s position: %9.3f", argv[i],
|
snprintf(pBueffel,511, "New %s position: %.6g", argv[i],
|
||||||
findPosition(pSics, pCon, argv[i]));
|
findPosition(pSics, pCon, argv[i]));
|
||||||
SCWrite(pCon, pBueffel, eValue);
|
SCWrite(pCon, pBueffel, eValue);
|
||||||
}
|
}
|
||||||
|
@ -133,13 +133,19 @@ int AnalyzeCommand(char *command) {
|
|||||||
|
|
||||||
Tcl_SplitList(NULL, command, &argc, &argv);
|
Tcl_SplitList(NULL, command, &argc, &argv);
|
||||||
arg0 = 0;
|
arg0 = 0;
|
||||||
if (argc > 0 && strcmp(argv[0], "fulltransact") == 0) {
|
if (argc > 0 && (strcmp(argv[0], "fulltransact") == 0
|
||||||
|
|| strcmp(argv[0], "transact") == 0)) {
|
||||||
arg0 = 1;
|
arg0 = 1;
|
||||||
}
|
}
|
||||||
if (argc <= arg0 + 1) {
|
if (argc <= arg0 + 1) {
|
||||||
writable = 0; /* single word -> guess read only */
|
writable = 0; /* single word -> guess read only */
|
||||||
goto Free;
|
goto Free;
|
||||||
}
|
}
|
||||||
|
if (strcmp(argv[arg0], "sicsdescriptor") == 0
|
||||||
|
|| strcmp(argv[arg0], "_tcl") == 0) {
|
||||||
|
writable = 0;
|
||||||
|
goto Free;
|
||||||
|
}
|
||||||
pDes = FindCommandDescriptor(pServ->pSics, argv[arg0]);
|
pDes = FindCommandDescriptor(pServ->pSics, argv[arg0]);
|
||||||
if (pDes == NULL) goto Free;
|
if (pDes == NULL) goto Free;
|
||||||
if (pDes->parNode == NULL && GetDescriptorKey(pDes, "pardef") == NULL) goto Free;
|
if (pDes->parNode == NULL && GetDescriptorKey(pDes, "pardef") == NULL) goto Free;
|
||||||
|
@ -31,7 +31,8 @@ static hdbCallbackReturn LoggerUpdateCallback(pHdb node,
|
|||||||
value = *(mm->v);
|
value = *(mm->v);
|
||||||
|
|
||||||
time(&now);
|
time(&now);
|
||||||
if (now > LoggerLastTime(logger)) { /* never write more than once per second */
|
/* testwise >= */
|
||||||
|
if (now >= LoggerLastTime(logger)) { /* never write more than once per second */
|
||||||
if (GetHdbProp(node, "geterror") == NULL) {
|
if (GetHdbProp(node, "geterror") == NULL) {
|
||||||
str = formatValue(value, node);
|
str = formatValue(value, node);
|
||||||
LoggerWrite(logger, time(NULL), LoggerPeriod(logger), GetCharArray(str));
|
LoggerWrite(logger, time(NULL), LoggerPeriod(logger), GetCharArray(str));
|
||||||
|
3
make_gen
3
make_gen
@ -45,7 +45,8 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
|||||||
singlenb.o simindex.o simidx.o uselect.o singletas.o motorsec.o \
|
singlenb.o simindex.o simidx.o uselect.o singletas.o motorsec.o \
|
||||||
rwpuffer.o asynnet.o background.o countersec.o hdbtable.o velosec.o \
|
rwpuffer.o asynnet.o background.o countersec.o hdbtable.o velosec.o \
|
||||||
histmemsec.o sansbc.o sicsutil.o strlutil.o genbinprot.o trace.o\
|
histmemsec.o sansbc.o sicsutil.o strlutil.o genbinprot.o trace.o\
|
||||||
singlebinb.o taskobj.o sctcomtask.o tasmono.o multicountersec.o lscprot.o \
|
singlebinb.o taskobj.o sctcomtask.o tasmono.o multicountersec.o\
|
||||||
|
lscprot.o secopprot.o\
|
||||||
messagepipe.o sicsget.o remoteobject.o pmacprot.o charbychar.o binprot.o \
|
messagepipe.o sicsget.o remoteobject.o pmacprot.o charbychar.o binprot.o \
|
||||||
cnvrt.o tclClock.o tclDate.o tclUnixTime.o stack_trace.o logv2.o outcode.o
|
cnvrt.o tclClock.o tclDate.o tclUnixTime.o stack_trace.o logv2.o outcode.o
|
||||||
|
|
||||||
|
2
ofac.c
2
ofac.c
@ -52,6 +52,7 @@ static void InitGeneral(void)
|
|||||||
INIT(AddPMACProtocoll);
|
INIT(AddPMACProtocoll);
|
||||||
INIT(AddCharByCharProtocoll);
|
INIT(AddCharByCharProtocoll);
|
||||||
INIT(AddLscProtocol);
|
INIT(AddLscProtocol);
|
||||||
|
INIT(AddSecopProtocol);
|
||||||
INIT(MakeTrace);
|
INIT(MakeTrace);
|
||||||
INIT(InitTaskOBJ);
|
INIT(InitTaskOBJ);
|
||||||
INIT(RemoteObjectInit);
|
INIT(RemoteObjectInit);
|
||||||
@ -121,6 +122,7 @@ static void InitIniCommands(SicsInterp * pInter)
|
|||||||
PCMD("SICSType", SICSType);
|
PCMD("SICSType", SICSType);
|
||||||
PCMD("Sics_Exitus", SicsExit);
|
PCMD("Sics_Exitus", SicsExit);
|
||||||
PCMD("silent", SICSSilent);
|
PCMD("silent", SICSSilent);
|
||||||
|
PCMD("json2tcl", SICSjson2tcl);
|
||||||
PCMD("status", UserStatus);
|
PCMD("status", UserStatus);
|
||||||
PCMD("TclReplaceDrivable", TclReplaceDrivable);
|
PCMD("TclReplaceDrivable", TclReplaceDrivable);
|
||||||
PCMD("transact", TransactAction);
|
PCMD("transact", TransactAction);
|
||||||
|
64
script.c
64
script.c
@ -43,7 +43,6 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <tcl.h>
|
|
||||||
#include "fortify.h"
|
#include "fortify.h"
|
||||||
#include "sics.h"
|
#include "sics.h"
|
||||||
#include "fupa.h"
|
#include "fupa.h"
|
||||||
@ -579,3 +578,66 @@ int SICSSilent(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
free(cmd);
|
free(cmd);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
Tcl_Obj *json2tcl(struct json_object *jobj) {
|
||||||
|
char buf[100];
|
||||||
|
int i, len;
|
||||||
|
Tcl_Obj **list;
|
||||||
|
Tcl_Obj *dict, *kobj, *vobj;
|
||||||
|
Tcl_Obj *val;
|
||||||
|
const char *key;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
switch (json_object_get_type(jobj)) {
|
||||||
|
case json_type_boolean:
|
||||||
|
return Tcl_NewBooleanObj(json_object_get_boolean(jobj));
|
||||||
|
case json_type_int:
|
||||||
|
return Tcl_NewLongObj(json_object_get_int(jobj));
|
||||||
|
case json_type_double:
|
||||||
|
return Tcl_NewDoubleObj(json_object_get_double(jobj));
|
||||||
|
case json_type_string:
|
||||||
|
str = json_object_get_string(jobj);
|
||||||
|
return Tcl_NewStringObj((char *)str, json_object_get_string_len(jobj));
|
||||||
|
case json_type_array:
|
||||||
|
len = json_object_array_length(jobj);
|
||||||
|
list = calloc(sizeof *list, len);
|
||||||
|
for (i=0; i<len; i++) {
|
||||||
|
list[i] = json2tcl(json_object_array_get_idx(jobj, i));
|
||||||
|
if (!list[i]) return NULL;
|
||||||
|
}
|
||||||
|
return Tcl_NewListObj(len, list);
|
||||||
|
case json_type_object:
|
||||||
|
dict = Tcl_NewDictObj();
|
||||||
|
if (!dict) return NULL;
|
||||||
|
json_object_object_foreach(jobj, key, val) {
|
||||||
|
kobj = Tcl_NewStringObj(key, strlen(key));
|
||||||
|
vobj = json2tcl(val);
|
||||||
|
if (kobj && vobj) {
|
||||||
|
Tcl_DictObjPut(NULL, dict, kobj, vobj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
return Tcl_NewStringObj("None", 4);
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
int SICSjson2tcl(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
|
int argc, char *argv[]) {
|
||||||
|
json_object *jobj;
|
||||||
|
assert(pCon);
|
||||||
|
assert(pSics);
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
SCWrite(pCon, "ERROR: should be: json2tcl <string>", eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
jobj = json_tokener_parse(argv[1]);
|
||||||
|
if (!jobj) {
|
||||||
|
SCWrite(pCon, "ERROR: no valid JSON", eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* the result is written only to the interpreter, no output to the client */
|
||||||
|
Tcl_SetObjResult(pSics->pTcl, json2tcl(jobj));
|
||||||
|
json_object_put(jobj);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
8
script.h
8
script.h
@ -10,6 +10,9 @@
|
|||||||
#ifndef SICSSCRIPT
|
#ifndef SICSSCRIPT
|
||||||
#define SICSSCRIPT
|
#define SICSSCRIPT
|
||||||
|
|
||||||
|
#include <tcl.h>
|
||||||
|
#include <json-c/json.h>
|
||||||
|
|
||||||
/* -------------------------- Interrupts -----------------------------------*/
|
/* -------------------------- Interrupts -----------------------------------*/
|
||||||
int GetSICSInterrupt(SConnection * pCon, SicsInterp * pSics, void *pData,
|
int GetSICSInterrupt(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||||
int argc, char *argv[]);
|
int argc, char *argv[]);
|
||||||
@ -51,4 +54,9 @@ int SICSDescriptor(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
int SICSSilent(SConnection *pCon, SicsInterp *pSics, void *pData,
|
int SICSSilent(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[]);
|
int argc, char *argv[]);
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
Tcl_Obj *json2tcl(struct json_object *jobj);
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
int SICSjson2tcl(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
|
int argc, char *argv[]);
|
||||||
#endif
|
#endif
|
||||||
|
@ -283,7 +283,11 @@ int SctCommand(SConnection * con, SicsInterp * sics, void *object,
|
|||||||
if (argc == 3) {
|
if (argc == 3) {
|
||||||
node = FindHdbNode(NULL, argv[2], con);
|
node = FindHdbNode(NULL, argv[2], con);
|
||||||
}
|
}
|
||||||
|
if (node) {
|
||||||
GetHdbPath(node->mama, value, sizeof value);
|
GetHdbPath(node->mama, value, sizeof value);
|
||||||
|
} else {
|
||||||
|
value[0] = 0;
|
||||||
|
}
|
||||||
/* returns an empty string on error */
|
/* returns an empty string on error */
|
||||||
SCWrite(con, value, eValue);
|
SCWrite(con, value, eValue);
|
||||||
return 1;
|
return 1;
|
||||||
@ -1733,6 +1737,22 @@ static int SctHostport(pSICSOBJ ccmd, SConnection * con,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int SctIpAddress(pSICSOBJ ccmd, SConnection * con,
|
||||||
|
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||||
|
{
|
||||||
|
SctController *c;
|
||||||
|
uint32_t ip;
|
||||||
|
|
||||||
|
c = (SctController *) ccmd->pPrivate;
|
||||||
|
ip = DevIP(c->devser);
|
||||||
|
SCPrintf(con, eValue, "%d.%d.%d.%d",
|
||||||
|
(int)(ip & 0xff),
|
||||||
|
(int)((ip >> 8) & 0xff),
|
||||||
|
(int)((ip >> 16) & 0xff),
|
||||||
|
(int)((ip >> 24) & 0xff));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int SctTimeout(pSICSOBJ ccmd, SConnection * con,
|
static int SctTimeout(pSICSOBJ ccmd, SConnection * con,
|
||||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||||
{
|
{
|
||||||
@ -1909,7 +1929,7 @@ static int SctMakeController(SConnection * con, SicsInterp * sics,
|
|||||||
assert(controller);
|
assert(controller);
|
||||||
controller->debugConn = NULL;
|
controller->debugConn = NULL;
|
||||||
|
|
||||||
ccmd = MakeSICSOBJv(objName, "SctController", HIPNONE, usSpy);
|
ccmd = MakeSICSOBJv(objName, "SctController", HIPTEXT, usSpy);
|
||||||
controller->node = ccmd->objectNode;
|
controller->node = ccmd->objectNode;
|
||||||
controller->conn = SCCreateDummyConnection(pServ->pSics);
|
controller->conn = SCCreateDummyConnection(pServ->pSics);
|
||||||
|
|
||||||
@ -2006,6 +2026,9 @@ static int SctMakeController(SConnection * con, SicsInterp * sics,
|
|||||||
cmd = AddSICSHdbPar(controller->node,
|
cmd = AddSICSHdbPar(controller->node,
|
||||||
"hostport", usSpy, MakeSICSFunc(SctHostport));
|
"hostport", usSpy, MakeSICSFunc(SctHostport));
|
||||||
|
|
||||||
|
cmd = AddSICSHdbPar(controller->node,
|
||||||
|
"ip", usSpy, MakeSICSFunc(SctIpAddress));
|
||||||
|
|
||||||
cmd = AddSICSHdbPar(controller->node,
|
cmd = AddSICSHdbPar(controller->node,
|
||||||
"status", usSpy, MakeSICSFunc(SctStatus));
|
"status", usSpy, MakeSICSFunc(SctStatus));
|
||||||
|
|
||||||
|
85
secopprot.c
Normal file
85
secopprot.c
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <tcl.h>
|
||||||
|
#include <json-c/json.h>
|
||||||
|
#include "ascon.h"
|
||||||
|
#include "ascon.i"
|
||||||
|
#include "script.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* protocol for SECoP
|
||||||
|
*
|
||||||
|
* Markus Zolliker June 2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
int SecopProtHandler(Ascon *a) {
|
||||||
|
int ret;
|
||||||
|
char *result;
|
||||||
|
char *space;
|
||||||
|
char *json;
|
||||||
|
Tcl_Obj *tcllist[3], *tclobj;
|
||||||
|
int l;
|
||||||
|
struct json_object *jobj;
|
||||||
|
|
||||||
|
switch (a->state) {
|
||||||
|
case AsconWriting:
|
||||||
|
/* do not skip garbage (might be a message!) */
|
||||||
|
l = GetDynStringLength(a->wrBuffer) - a->wrPos;
|
||||||
|
ret = AsconWriteChars(a->fd, GetCharArray(a->wrBuffer) + a->wrPos, l);
|
||||||
|
if (ret < 0) {
|
||||||
|
AsconError(a, "ASC4", errno); /* sets state to AsconFailed */
|
||||||
|
} else {
|
||||||
|
a->wrPos += ret;
|
||||||
|
if (a->wrPos >= GetDynStringLength(a->wrBuffer)) {
|
||||||
|
a->state = AsconWriteDone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
case AsconWriteStart:
|
||||||
|
if (GetDynStringLength(a->wrBuffer) == 0) {
|
||||||
|
/* do not send empty message */
|
||||||
|
a->state = AsconWriteDone;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret = AsconStdHandler(a);
|
||||||
|
switch (a->state) {
|
||||||
|
case AsconReading:
|
||||||
|
if (ret) {
|
||||||
|
if (a->timeout < 1) {
|
||||||
|
/* extend timeout to 1 sec during a message */
|
||||||
|
a->start = DoubleTime() + 1 - a->timeout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AsconReadDone:
|
||||||
|
result = GetCharArray(a->rdBuffer);
|
||||||
|
space = strchr(result, ' ');
|
||||||
|
if (space) {
|
||||||
|
json = strchr(space+1, ' ');
|
||||||
|
if (json) {
|
||||||
|
json++;
|
||||||
|
jobj = json_tokener_parse(json);
|
||||||
|
if (jobj) {
|
||||||
|
tcllist[0] = Tcl_NewStringObj(result, space - result);
|
||||||
|
tcllist[1] = Tcl_NewStringObj(space + 1, json - space - 2);
|
||||||
|
tcllist[2] = json2tcl(jobj);
|
||||||
|
tclobj = Tcl_NewListObj(3, tcllist);
|
||||||
|
DynStringCopy(a->rdBuffer, Tcl_GetString(tclobj));
|
||||||
|
json_object_put(jobj); /* free jobj */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
void AddSecopProtocol() {
|
||||||
|
static AsconProtocol secopprot;
|
||||||
|
secopprot.name = "SECoP";
|
||||||
|
secopprot.handler = SecopProtHandler;
|
||||||
|
secopprot.init = AsconStdInit;
|
||||||
|
AsconInsertProtocol(&secopprot);
|
||||||
|
}
|
Reference in New Issue
Block a user