From fdb443441ab949bb30fb31d6e813848ec9cffb1f Mon Sep 17 00:00:00 2001 From: Markus Zolliker Date: Fri, 13 May 2016 16:32:18 +0200 Subject: [PATCH] - more AsconStatus states - enhancements in binprot - make Logger public (logger.h) - added lscprot (50 ms write delay for lakeshore models) - additonal bug fixes --- ascon.c | 3 +- ascon.h | 1 + binprot.c | 50 +++++++++++++++++++++------ devser.c | 1 + logger.c | 21 +++++------- logger.h | 15 +++++++- lscprot.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ make_gen | 2 +- ofac.c | 1 + remob.c | 2 +- 10 files changed, 169 insertions(+), 28 deletions(-) create mode 100644 lscprot.c diff --git a/ascon.c b/ascon.c index 1eb23b90..42906fb7 100644 --- a/ascon.c +++ b/ascon.c @@ -669,6 +669,7 @@ Ascon *AsconMake(SConnection * con, int argc, char *argv[]) a->responseValid = 0; a->readState = 0; a->lineCount = 1; + a->separator = NULL; a->killPrivate = NULL; a->private = NULL; @@ -752,7 +753,7 @@ AsconStatus AsconTask(Ascon * a) case AsconNotConnected: return AsconOffline; case AsconConnecting: - return AsconUnconnected; + return AsconConnectPending; case AsconConnectDone: a->state = AsconIdle; DynStringClear(a->errmsg); /* connection o.k. */ diff --git a/ascon.h b/ascon.h index c7f81933..2571fd8c 100644 --- a/ascon.h +++ b/ascon.h @@ -17,6 +17,7 @@ typedef struct Ascon Ascon; typedef enum { AsconOffline, AsconUnconnected, + AsconConnectPending, AsconPending, AsconReady, AsconFailure /* codes after this indicate also failure */ diff --git a/binprot.c b/binprot.c index 99261994..f65511ae 100644 --- a/binprot.c +++ b/binprot.c @@ -27,6 +27,7 @@ * * and formatItem is one of the follwing * + * a number (decimal format): returned byte must match (else error) * skip skip one byte * skip skip bytes * code returned function code, when bit7 is set, the response is @@ -39,6 +40,7 @@ * and append it to the response * float convert 4 bytes from ieee float * and append the number to the response + * dump read all bytes in read buffer as hex (only for tests) * crc check crc (if wrong, "badCRC" is added to the response) * * multiple items in the response are space separated @@ -49,16 +51,16 @@ * * sct send 250 3 int2 10 2 crc / skip code skip float crc * - * different crc's might be used (argv[2] opf BinInit): + * different crc's might be used (argv[2] of BinInit): * modbus-crc: CRC-16-IBM, order: lo,hi * keller-crc: CRC-16-IBM, order: hi,lo * sycon-crc: sort of mod 256 checksum, byte stuffing included (no float allowed) * chksum-crc: simple 8bit checksum */ -typedef enum {intType, hexType, floatType, - skipType, codeType, crcType, dumpType, errorType} BinDataType; -// dumpType, errorType must be the last items +typedef enum {intType, hexType, floatType, skipType, codeType, checkType, + crcType, dumpType, endType, errorType} BinDataType; +// dumpType, endType, errorType must be the last items typedef enum {modbusCrc, kellerCrc, rsportCrc, syconCrc, chksumCrc} CrcAlgorithm; @@ -164,7 +166,7 @@ int BinReadItem(Ascon *a) { if (sscanf(p->nextFmt, "%30s%n", item, &valen) <= 0) { if (p->type < dumpType) { p->dumpFrom = GetDynStringLength(a->rdBuffer); - p->type= dumpType; + p->type = endType; } p->expectedChars = 999; return 0; @@ -193,13 +195,22 @@ int BinReadItem(Ascon *a) { p->type = hexType; } else if (strcasecmp(item, "code") == 0) { p->type = codeType; + } else if (strcasecmp(item, "dump") == 0) { + p->dumpFrom = GetDynStringLength(a->rdBuffer); + p->type = dumpType; } else if (strncasecmp(item, "skip", 4) == 0) { size = 1; sscanf(item + 4, "%d", &size); p->expectedChars = size; p->type = skipType; - } else { - return -1; + } else { + p->iValue = 0; + if (1 == sscanf(item, "%ld", &p->iValue)) { + p->expectedChars = 1; + p->type = checkType; + } else { + return -1; + } } p->nextFmt += valen; return 1; @@ -268,6 +279,7 @@ int BinHandler(Ascon *a) { int valen; BinDataType type; long iValue; + unsigned long uValue; double fValue; BinPrivate *p = a->private; @@ -327,11 +339,12 @@ int BinHandler(Ascon *a) { BinError(a, "invalid integer"); return 1; } + uValue = iValue; for (i = size - 1; i >= 0; i--) { if (i < sizeof data) { - data[i] = iValue % 256; + data[i] = uValue % 256; } - iValue /= 256; + uValue >>= 8; } for (i = 0; i < size; i++) { if (i >= sizeof data) { @@ -411,7 +424,11 @@ int BinHandler(Ascon *a) { snprintf(item, sizeof item, "%2.2x ", (str[i] & 255)); DynStringConcat(p->result, item); } - if (p->type == errorType) { + if (p->type == endType && p->dumpFrom < l) { + DynStringCopy(a->errmsg, "BINERR: superflous chars "); + DynStringConcat(a->errmsg, GetCharArray(p->result)); + a->state = AsconFailed; + } else if (p->type == errorType) { DynStringConcat(a->errmsg, GetCharArray(p->result)); a->state = AsconFailed; } else { @@ -492,6 +509,7 @@ int BinHandler(Ascon *a) { DynStringCopy(p->result, item); } break; + case endType: case dumpType: break; case skipType: @@ -500,7 +518,7 @@ int BinHandler(Ascon *a) { case intType: p->expectedChars--; p->iValue = p->iValue * 256 + (a->lastChar & 255); - if (p->expectedChars <= 0) { + if (p->expectedChars <= 0) { snprintf(item, sizeof item, "%ld ", p->iValue); DynStringConcat(p->result, item); } @@ -555,6 +573,16 @@ int BinHandler(Ascon *a) { /* subtract CRC char (undo the addition) and subtract crc higher four bits */ p->chksum -= a->lastChar + (a->lastChar & 0x0f) * 16; } + break; + case checkType: + p->expectedChars--; + if ((a->lastChar & 255) != p->iValue) { + DynStringCopy(a->errmsg, "BINERR: mismatch "); + p->type = errorType; + p->dumpFrom = 0; + /* skip to end */ + p->nextFmt = ""; + } } if (p->expectedChars <= 0) { BinReadItem(a); diff --git a/devser.c b/devser.c index 076ee6ae..b3888e51 100644 --- a/devser.c +++ b/devser.c @@ -580,6 +580,7 @@ char *DevStatus(DevSer *devser) { switch (devser->status) { case AsconOffline: return "disconnected"; case AsconUnconnected: return "unconnected"; + case AsconConnectPending: return "connecting"; /* case AsconPending: return "busy"; case AsconReady: return "ready"; diff --git a/logger.c b/logger.c index bcf7c682..4534ce40 100644 --- a/logger.c +++ b/logger.c @@ -15,18 +15,6 @@ Markus Zolliker, Sept 2004 #include #include "logger.h" -struct Logger { - char *name; - char *old; - int oldsize; - int period; - time_t last, lastWrite, omitTime; - int numeric; - float omitValue; - int exact; - Logger *next; -}; - static char *dir = NULL; static Logger *list; static time_t lastLife = 0; @@ -152,6 +140,7 @@ int LoggerWrite0(Logger * log, time_t now, int period, char *value) int l, ext, writeInfo; FILE *fil; time_t beforenow; + char *nl; if (log->name[0] == '\0') return 0; @@ -211,7 +200,13 @@ int LoggerWrite0(Logger * log, time_t now, int period, char *value) } } strftime(stim, sizeof stim, "%H:%M:%S", &tm); - fprintf(fil, "%s\t%s\n", stim, value); + nl = strchr(value, '\n'); + if (nl == NULL) { + fprintf(fil, "%s\t%s\n", stim, value); + } else { + /* newline within string! do write only characters before nl */ + fprintf(fil, "%s\t%.*s\n", stim, (nl - value), value); + } log->lastWrite = now; fclose(fil); diff --git a/logger.h b/logger.h index a8404c4e..2f9ab189 100644 --- a/logger.h +++ b/logger.h @@ -10,7 +10,20 @@ Markus Zolliker, Sept 2004 #include -typedef struct Logger Logger; +typedef struct Logger { + /* public */ + char *name; + int numeric; + int period; + int exact; + /* private: */ + char *old; + int oldsize; + time_t last, lastWrite, omitTime; + float omitValue; + struct Logger *next; +} Logger; + Logger *LoggerMake(char *name, int period, int exact); void LoggerKill(Logger * log); diff --git a/lscprot.c b/lscprot.c new file mode 100644 index 00000000..c6b24828 --- /dev/null +++ b/lscprot.c @@ -0,0 +1,101 @@ +#include "ascon.h" +#include "ascon.i" + +/* + * script context protocol for LakeShore 370 / 340 etc. models + * a 50 msec waiting time is needed after each reply / command + * + * Markus Zolliker May 2016 + */ + +typedef struct { + double last; + double delay; +} LscPrivate; + +/*----------------------------------------------------------------------------*/ +int LscProtHandler(Ascon *a) +{ + LscPrivate *p; + int res; + + if (a->state == AsconWriteStart) { + p = a->private; + if (DoubleTime() < p->last + p->delay) { // 50 msec + return 0; + } + } + res = AsconStdHandler(a); + if (a->state == AsconReadDone) { + p = a->private; + p->last = DoubleTime(); + } + return res; +} + +/*----------------------------------------------------------------------------*/ +static void LscPrivateKill(void *p) { + free(p); +} + +/*----------------------------------------------------------------------------*/ +int LscProtInit(Ascon *a, SConnection *con, int argc, char *argv[]) +{ + enum nPars {NA=4}; + char *pars[NA]; + static char *parn[NA]={ + "sendterminator", + "timeout", + "replyterminator", + "writedelay" + }; + char *msg; + LscPrivate *p; + + assert(argc>1); + a->hostport = strdup(argv[1]); + + if (!AsconInterpreteArgs(argc-2, argv+2, NA, parn, pars)) { + return 0; + } + + p = calloc(sizeof(*p), 1); + if (p == NULL) return 0; + + p->last = DoubleTime(); + a->private = p; + a->killPrivate = LscPrivateKill; + + if (pars[0]) { + a->sendTerminator = strdup(pars[0]); + } else { + a->sendTerminator = strdup("\n"); + } + if (pars[1] && pars[1][0] != '\0') { + a->timeout = atof(pars[1]); + } else { + a->timeout = 2.0; /* sec */ + } + if (pars[2] && pars[2][0] != '\0') { + a->replyTerminator = strdup(pars[2]); + } else { + a->replyTerminator = NULL; + } + if (pars[3] && pars[3][0] != '\0') { + p->delay = atof(pars[3]); + } else { + p->delay = 0.05; + } + AsconCheckTerminators(a); + return 1; +} + +/*----------------------------------------------------------------------------*/ +void AddLscProtocol() +{ + static AsconProtocol lscprot; + lscprot.name = "lsc"; + lscprot.handler = LscProtHandler; + lscprot.init = LscProtInit; + AsconInsertProtocol(&lscprot); +} diff --git a/make_gen b/make_gen index f4f8cad0..cbdd5be6 100644 --- a/make_gen +++ b/make_gen @@ -45,7 +45,7 @@ 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 \ rwpuffer.o asynnet.o background.o countersec.o hdbtable.o velosec.o \ histmemsec.o sansbc.o sicsutil.o strlutil.o genbinprot.o trace.o\ - singlebinb.o taskobj.o sctcomtask.o tasmono.o multicountersec.o \ + singlebinb.o taskobj.o sctcomtask.o tasmono.o multicountersec.o lscprot.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 diff --git a/ofac.c b/ofac.c index df88921e..5d2f1f77 100644 --- a/ofac.c +++ b/ofac.c @@ -51,6 +51,7 @@ static void InitGeneral(void) INIT(AddBinProtocol); INIT(AddPMACProtocoll); INIT(AddCharByCharProtocoll); + INIT(AddLscProtocol); INIT(MakeTrace); INIT(InitTaskOBJ); INIT(RemoteObjectInit); diff --git a/remob.c b/remob.c index 35eb4d98..44995006 100644 --- a/remob.c +++ b/remob.c @@ -29,7 +29,7 @@ typedef struct RemChannel { mkChannel *chan; int timeout; int incomplete; - char line[256]; + char line[1024]; } RemChannel; typedef struct RemServer {