bugfixes in drivers

This commit is contained in:
zolliker
2011-08-29 11:55:12 +00:00
parent b0fca0f96f
commit 01ecc51a4a
7 changed files with 259 additions and 42 deletions

197
binprot.c
View File

@ -48,14 +48,21 @@
* response: address, function, byte-count, float, crc * response: address, function, byte-count, float, crc
* *
* sct send 250 3 int2 10 2 crc / skip code skip float crc * sct send 250 3 int2 10 2 crc / skip code skip float crc
*
* different crc's might be used (argv[2] opf 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)
*/ */
typedef enum {intType, hexType, floatType, typedef enum {intType, hexType, floatType,
skipType, codeType, crcType, dumpType, errorType} BinDataType; skipType, codeType, crcType, dumpType, errorType} BinDataType;
// dumpType, errorType must be the last items // dumpType, errorType must be the last items
typedef enum {modbusCrc, kellerCrc, syconCrc} CrcAlgorithm;
typedef struct { typedef struct {
char *crcAlgorithm; CrcAlgorithm crcAlgorithm;
pDynString inp; pDynString inp;
char *nextFmt; char *nextFmt;
pDynString result; pDynString result;
@ -63,16 +70,20 @@ typedef struct {
BinDataType type; BinDataType type;
long iValue; long iValue;
int dumpFrom; int dumpFrom;
int syconState;
unsigned char chksum;
} BinPrivate; } BinPrivate;
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
static int calc_crc(char *inp, int inpLen) static int calc_crc(char *inp, int inpLen)
{ {
/** CRC-16-IBM Algorithm
/* CRC runs cyclic Redundancy Check Algorithm on input inp */ * crc calculation:
/* Returns value of 16 bit CRC after completion and */ * returns the 16bit CRC value of a message
/* always adds 2 crc bytes to message */ * crc check:
/* returns 0 if incoming message has correct CRC */ * returns 0 when the crc appended to the message (lo byte first)
* is correct
*/
unsigned int crc = 0xffff; unsigned int crc = 0xffff;
unsigned int next; unsigned int next;
@ -154,6 +165,42 @@ void BinError(Ascon *a, char *text) {
a->state = AsconFailed; a->state = AsconFailed;
} }
/*----------------------------------------------------------------------------*/
void BinToSycon(pDynString dyn) {
char *str = strdup(GetCharArray(dyn));
int l = GetDynStringLength(dyn);
unsigned char sum, byte;
int i;
DynStringClear(dyn);
DynStringConcat(dyn, "\x02\x10\x80"); /* STX ADDR CMD */
sum = 0x10 + 0x80;
for (i=0; i<l; i++) {
byte = str[i];
sum += byte;
switch (byte) {
case 0x02:
DynStringConcatChar(dyn, 0x07);
DynStringConcatChar(dyn, '0');
break;
case 0x0d:
DynStringConcatChar(dyn, 0x07);
DynStringConcatChar(dyn, '1');
break;
case 0x07:
DynStringConcatChar(dyn, 0x07);
DynStringConcatChar(dyn, '2');
break;
default:
DynStringConcatChar(dyn, byte);
}
}
DynStringConcatChar(dyn, 0x30 + (sum / 16));
DynStringConcatChar(dyn, 0x30 + (sum % 16));
DynStringConcatChar(dyn, 0x0d);
free(str);
}
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
int BinHandler(Ascon *a) { int BinHandler(Ascon *a) {
int res; int res;
@ -192,14 +239,17 @@ int BinHandler(Ascon *a) {
if (strcasecmp(item, "/") == 0) { if (strcasecmp(item, "/") == 0) {
break; break;
} else if (strcasecmp(item, "crc") == 0) { } else if (strcasecmp(item, "crc") == 0) {
if (strcasecmp(p->crcAlgorithm, "keller-crc") == 0) { switch (p->crcAlgorithm) {
case kellerCrc:
crc = calc_crc(GetCharArray(dyn), l); crc = calc_crc(GetCharArray(dyn), l);
DynStringConcatChar(dyn, crc / 256); DynStringConcatChar(dyn, crc / 256);
DynStringConcatChar(dyn, crc % 256); DynStringConcatChar(dyn, crc % 256);
} else { /* modbus-crc */ break;
case modbusCrc:
crc = calc_crc(GetCharArray(dyn), l); crc = calc_crc(GetCharArray(dyn), l);
DynStringConcatChar(dyn, crc / 256);
DynStringConcatChar(dyn, crc % 256); DynStringConcatChar(dyn, crc % 256);
DynStringConcatChar(dyn, crc / 256);
break;
} }
} else if (strncasecmp(item, "int", 3) == 0) { } else if (strncasecmp(item, "int", 3) == 0) {
sscanf(item + 3, "%d", &size); sscanf(item + 3, "%d", &size);
@ -238,6 +288,7 @@ int BinHandler(Ascon *a) {
return 1; return 1;
} }
DynStringConcatChar(dyn, (iValue & 255)); DynStringConcatChar(dyn, (iValue & 255));
break;
case floatType: case floatType:
res = sscanf(item, "%lf", &fValue); res = sscanf(item, "%lf", &fValue);
if (res != 1) { if (res != 1) {
@ -255,6 +306,10 @@ int BinHandler(Ascon *a) {
} }
} }
if (p->crcAlgorithm == syconCrc) {
BinToSycon(dyn);
}
p->nextFmt = str + pos; p->nextFmt = str + pos;
p->type = hexType; /* initialize to anything < dumpType */ p->type = hexType; /* initialize to anything < dumpType */
do { do {
@ -274,6 +329,7 @@ int BinHandler(Ascon *a) {
DynStringClear(p->result); DynStringClear(p->result);
p->type = hexType; /* initialize to anything < dumpType */ p->type = hexType; /* initialize to anything < dumpType */
BinReadItem(a); BinReadItem(a);
p->syconState = 0;
break; break;
case AsconReading: case AsconReading:
res = AsconBaseHandler(a); res = AsconBaseHandler(a);
@ -283,12 +339,12 @@ int BinHandler(Ascon *a) {
return res; return res;
} }
if (p->type >= dumpType) { if (p->type >= dumpType) {
l = GetDynStringLength(a->rdBuffer); l = GetDynStringLength(a->rdBuffer);
str = GetCharArray(a->rdBuffer); str = GetCharArray(a->rdBuffer);
for (i = p->dumpFrom; i < l; i++) { for (i = p->dumpFrom; i < l; i++) {
snprintf(item, sizeof item, "%2.2x ", (str[i] & 255)); snprintf(item, sizeof item, "%2.2x ", (str[i] & 255));
DynStringConcat(p->result, item); DynStringConcat(p->result, item);
} }
if (p->type == errorType) { if (p->type == errorType) {
DynStringConcat(a->errmsg, GetCharArray(p->result)); DynStringConcat(a->errmsg, GetCharArray(p->result));
a->state = AsconFailed; a->state = AsconFailed;
@ -297,12 +353,58 @@ int BinHandler(Ascon *a) {
} }
/* exchange buffers */ /* exchange buffers */
dyn = a->rdBuffer; dyn = a->rdBuffer;
a->rdBuffer = p->result; a->rdBuffer = p->result;
p->result = dyn; p->result = dyn;
return 1; return 1;
} }
return res; return res;
} }
if (p->crcAlgorithm == syconCrc) {
switch (p->syconState) {
case 0: /* wait for STX */
if (a->lastChar == 0x02) {
p->syconState = 1;
p->chksum = 0;
}
return res;
case 1: /* skip address */
case 2: /* skip cmd_rsp */
p->syconState++;
p->chksum += a->lastChar;
return res;
case 3: /* detect stuffed bytes */
if (a->lastChar == 0x07) {
p->syconState = 4;
return res;
}
p->chksum += a->lastChar;
break;
case 4: /* last byte was 0x07 */
switch (a->lastChar) {
case '0':
a->lastChar = 0x02;
break;
case '1':
a->lastChar = 0x0d;
break;
case '2':
a->lastChar = 0x07;
break;
}
p->chksum += a->lastChar;
p->syconState = 3;
break;
case 5: /* expect 0x0d */
if (a->lastChar != 0x0d) {
DynStringConcat(p->result, "noCR ");
}
p->syconState = 6;
p->dumpFrom++; /* skip for dump */
case 6: /* skip everything else */
return res;
}
}
/* convert according to type */ /* convert according to type */
switch (p->type) { switch (p->type) {
case codeType: case codeType:
@ -311,16 +413,16 @@ int BinHandler(Ascon *a) {
} else { } else {
DynStringCopy(a->errmsg, "BINERR: "); DynStringCopy(a->errmsg, "BINERR: ");
p->expectedChars = 2; p->expectedChars = 2;
p->type = errorType; p->type = errorType;
p->dumpFrom = 0; p->dumpFrom = 0;
/* skip to end */ /* skip to end */
p->nextFmt = ""; p->nextFmt = "";
} }
break; break;
case errorType: case errorType:
if (p->expectedChars > 1) { if (p->expectedChars > 1) {
p->expectedChars--; p->expectedChars--;
snprintf(item, sizeof item, "error %d / ", (a->lastChar & 255)); snprintf(item, sizeof item, "error %d / ", (a->lastChar & 255));
DynStringCopy(p->result, item); DynStringCopy(p->result, item);
} }
break; break;
@ -344,7 +446,7 @@ int BinHandler(Ascon *a) {
DynStringConcat(p->result, item); DynStringConcat(p->result, item);
} }
break; break;
case floatType: case floatType: /* does not work with sycon when stuffed */
p->expectedChars--; p->expectedChars--;
if (p->expectedChars <= 0) { if (p->expectedChars <= 0) {
str = GetCharArray(a->rdBuffer) + GetDynStringLength(a->rdBuffer) - 4; str = GetCharArray(a->rdBuffer) + GetDynStringLength(a->rdBuffer) - 4;
@ -358,14 +460,28 @@ int BinHandler(Ascon *a) {
if (p->expectedChars <= 0) { if (p->expectedChars <= 0) {
str = GetCharArray(a->rdBuffer); str = GetCharArray(a->rdBuffer);
l = GetDynStringLength(a->rdBuffer); l = GetDynStringLength(a->rdBuffer);
if (strcasecmp(p->crcAlgorithm, "keller-crc") == 0) { switch (p->crcAlgorithm) {
case syconCrc: /* ignore crc check */
/* subtract CRC char (undo the addition) and subtract crc higher four bits */
p->chksum -= a->lastChar + (a->lastChar & 0x0f);
p->syconState = 5;
if (p->chksum != 0) {
DynStringConcat(p->result, "badCRC ");
}
break;
case kellerCrc:
i = str[l-2]; i = str[l-2];
str[l-2] = str[l-1]; str[l-2] = str[l-1];
str[l-1] = i; str[l-1] = i;
/* fall through */
case modbusCrc:
if (calc_crc(str, l) != 0) {
DynStringConcat(p->result, "badCRC ");
}
} }
if (calc_crc(str, l) != 0) { } else if (p->crcAlgorithm == syconCrc) {
DynStringConcat(p->result, "badCRC "); /* subtract CRC char (undo the addition) and subtract crc higher four bits */
} p->chksum -= a->lastChar + (a->lastChar & 0x0f) * 16;
} }
} }
if (p->expectedChars <= 0) { if (p->expectedChars <= 0) {
@ -376,11 +492,10 @@ int BinHandler(Ascon *a) {
return AsconBaseHandler(a); return AsconBaseHandler(a);
} }
void BinPrivateKill(void *pVoid) { static void BinPrivateKill(void *pVoid) {
BinPrivate *p = pVoid; BinPrivate *p = pVoid;
DeleteDynString(p->inp); DeleteDynString(p->inp);
DeleteDynString(p->result); DeleteDynString(p->result);
free(p->crcAlgorithm);
free(p); free(p);
} }
@ -388,18 +503,30 @@ static int BinInit(Ascon * a, SConnection * con, int argc, char *argv[])
{ {
BinPrivate *p; BinPrivate *p;
/* argv[2] may be modbus-crc (default) or keller-crc */ /* argv[2] may be modbus-crc (default), keller-crc or sycon-crc */
if (argc < 2) {
return 0;
}
p = calloc(sizeof(*p), 1); p = calloc(sizeof(*p), 1);
a->hostport = strdup(argv[1]);
a->private = p; a->private = p;
a->killPrivate = BinPrivateKill;
p->crcAlgorithm = modbusCrc;
if (argc > 2 && strcmp(argv[2], "") != 0) {
if (strcasecmp(argv[2], "keller-crc") == 0) {
p->crcAlgorithm = kellerCrc;
} else if (strcasecmp(argv[2], "sycon-crc") == 0) {
p->crcAlgorithm = syconCrc;
} else if (strcasecmp(argv[2], "modbus-crc") != 0) {
SCPrintf(con, eError, "ERROR: unknown crc-algorithm %s", argv[2]);
a->private = NULL;
free(p);
return 0;
}
}
a->hostport = strdup(argv[1]);
p->inp = CreateDynString(60,63); p->inp = CreateDynString(60,63);
p->result = CreateDynString(60,63); p->result = CreateDynString(60,63);
if (argc > 2 && strcmp(argv[2], "") != 0) {
p->crcAlgorithm = strdup(argv[2]);
} else {
p->crcAlgorithm = strdup("modbus-crc");
}
if (argc > 3) { if (argc > 3) {
a->timeout = atof(argv[3]); a->timeout = atof(argv[3]);
} else { } else {

View File

@ -46,6 +46,9 @@ typedef struct {
float perslimit; /* field limit for activating persistent mode workaround (Tesla) */ float perslimit; /* field limit for activating persistent mode workaround (Tesla) */
float voltage; /* voltage */ float voltage; /* voltage */
float measured; /* measured current */ float measured; /* measured current */
float inductance; /* induction (read only on startup) */
float ampRamp; /* ramp in amps (read only on startup) */
char *startScript; /* script to be called on startup */
int persmode; /* 0: delayed persistant mode, 1: go to persistant mode, 2: leave switch on */ int persmode; /* 0: delayed persistant mode, 1: go to persistant mode, 2: leave switch on */
int persdelay; /* wait time for delayed persistant mode */ int persdelay; /* wait time for delayed persistant mode */
int perswitch; /* state of switch */ int perswitch; /* state of switch */
@ -234,6 +237,24 @@ void IpsParDef(void *object)
ParSave(1); ParSave(1);
ParFloat(&drv->lastfield, PAR_NAN); ParFloat(&drv->lastfield, PAR_NAN);
ParName("ampRamp");
ParFmt("%g");
ParTail("A");
ParList("");
ParFloat(&drv->ampRamp, 0.0);
ParName("inductance");
ParFmt("%g");
ParTail("Henry");
ParList("");
ParFloat(&drv->inductance, 0.0);
ParName("startScript");
ParAccess(usUser);
ParList("");
ParSave(1);
ParStr(&drv->startScript, "0");
ParName("confirm"); ParName("confirm");
ParCmd(IpsConfirm, NULL); ParCmd(IpsConfirm, NULL);
@ -519,6 +540,9 @@ static long IpsStart(long pc, void *object)
{ {
Ips *drv = ParCast(&ipsClass, object); Ips *drv = ParCast(&ipsClass, object);
EaseBase *eab = object; EaseBase *eab = object;
float value;
Tcl_Interp *pTcl = NULL;
int iRet;
switch (pc) { switch (pc) {
default: /* FSM BEGIN ****************************** */ default: /* FSM BEGIN ****************************** */
@ -532,7 +556,7 @@ static long IpsStart(long pc, void *object)
} else { } else {
snprintf(eab->msg, sizeof eab->msg, snprintf(eab->msg, sizeof eab->msg,
"unknown power supply version: %s", eab->version); "unknown power supply version: %s", eab->version);
ParPrintf(drv, eError, "ERROR: %s", eab->msg); ParPrintf(drv, eLogError, "ERROR: %s", eab->msg);
EaseStop(eab); EaseStop(eab);
goto quit; goto quit;
} }
@ -548,6 +572,63 @@ static long IpsStart(long pc, void *object)
case __LINE__: /**********************************/ case __LINE__: /**********************************/
drv->d.targetValue = drv->persfield; drv->d.targetValue = drv->persfield;
if (eab->syntax == 0) goto quit;
EaseWrite(eab, "R24");
return __LINE__;
case __LINE__:
drv->inductance = OxiGet(eab, 1, NULL, 0.0);
if (drv->ramp == 0) {
goto ramp_read;
}
EaseWrite(eab, "R9");
return __LINE__;
case __LINE__:
value = OxiGet(eab, 3, NULL, drv->ramp);
if (fabs(value - drv->ramp) == 0) goto ramp_ok;
EaseWrite(eab, "C3");
drv->remote = 1; /* remote state */
return __LINE__;
case __LINE__: /**********************************/
OxiSet(eab, "T", drv->ramp, 3);
return __LINE__;
case __LINE__: /**********************************/
EaseWrite(eab, "C0");
drv->remote = 0; /* local state */
return __LINE__;
case __LINE__: /**********************************/
ramp_read:
EaseWrite(eab, "R9");
return __LINE__;
case __LINE__:
drv->ramp = OxiGet(eab, 3, NULL, drv->ramp);
ramp_ok:
EaseWrite(eab, "R6");
return __LINE__;
case __LINE__:
drv->ampRamp = OxiGet(eab, 1, NULL, 0.0);
if (drv->startScript && drv->startScript[0] != '\0'
&& 0 != strcmp(drv->startScript, "0")) {
pTcl = InterpGetTcl(pServ->pSics);
iRet = Tcl_Eval(pTcl, drv->startScript);
if (iRet != TCL_OK) {
snprintf(eab->msg, sizeof eab->msg, "%s", pTcl->result);
ParPrintf(drv, eLogError, "ERROR: %s", eab->msg);
EaseStop(eab);
goto quit;
}
eab->msg[0]='\0';
}
quit: quit:
return 0; return 0;
} /* FSM END ******************************************* */ } /* FSM END ******************************************* */

View File

@ -30,7 +30,7 @@ OBJ=psi.o buffer.o ruli.o sps.o pimotor.o charbychar.o\
MZOBJ=fsm.o sugar.o pardef.o ease.o strobj.o oxinst.o \ MZOBJ=fsm.o sugar.o pardef.o ease.o strobj.o oxinst.o \
ipsdriv.o ilmdriv.o itcdriv.o ighdriv.o euro2kdriv.o modbus.o arrobj.o \ ipsdriv.o ilmdriv.o itcdriv.o ighdriv.o euro2kdriv.o modbus.o arrobj.o \
lscsupport.o lsc370driv.o linadriv.o haakedriv.o amilevel.o binprot.o \ lscsupport.o lsc370driv.o linadriv.o haakedriv.o amilevel.o binprot.o \
cnvrt.o cnvrt.o dumprot.o
libpsi.a: $(OBJ) libpsi.a: $(OBJ)
rm -f libpsi.a rm -f libpsi.a

View File

@ -444,9 +444,17 @@ void ParSaveConn(void *object, SConnection * con)
rights = SCGetRights(con); rights = SCGetRights(con);
if (rights >= usMugger && rights <= usUser && con->sockHandle >= 0) { if (rights >= usMugger && rights <= usUser && con->sockHandle >= 0) {
if (o->conn != NULL) { if (o->conn != NULL) {
SCDeleteConnection(o->conn); if (o->conn->ident != con->ident) {
SCDeleteConnection(o->conn);
o->conn = SCCopyConnection(con);
}
} else {
o->conn = SCCopyConnection(con);
}
SCsetMacro(o->conn, 0);
if (o->conn->write != SCNormalWrite) {
o->conn->write = SCNormalWrite;
} }
o->conn = SCCopyConnection(con);
} }
} }

View File

@ -129,7 +129,7 @@ void ParSave(int save); /* save on status file (0: do not svae, 1: save,
void ParEnum(char *list[]); /* automatic keyword to number conversion */ void ParEnum(char *list[]); /* automatic keyword to number conversion */
void ParList(char *group); /* ParList may be repeated with several group arguments, void ParList(char *group); /* ParList may be repeated with several group arguments,
to appear on a list <group> subcommand. Give NULL to appear on a list <group> subcommand. Give NULL
for std list. */ for std list, "" for no list */
void ParTail(char *tail); /* comment to appear after list entry (e.g. units). void ParTail(char *tail); /* comment to appear after list entry (e.g. units).
If ParList is not called, ParTail will force to appear If ParList is not called, ParTail will force to appear
in standard list. */ in standard list. */

1
psi.c
View File

@ -73,6 +73,7 @@ void SiteInit(void)
INIT(AddSLSEchoProtocoll); INIT(AddSLSEchoProtocoll);
INIT(AddCharByCharProtocoll); INIT(AddCharByCharProtocoll);
INIT(AddBinProtocol); INIT(AddBinProtocol);
INIT(AddDumProtocol);
} }

View File

@ -157,7 +157,7 @@ static void sendPost(pHttpProt pHttp, char *path, char *data)
snprintf(buffer,1024,"POST %s HTTP/1.1\r\nHost: %s\r\nConnection: keep-alive\r\n", snprintf(buffer,1024,"POST %s HTTP/1.1\r\nHost: %s\r\nConnection: keep-alive\r\n",
path, hostname); path, hostname);
ANETwrite(pHttp->sockHandle, buffer,strlen(buffer)); ANETwrite(pHttp->sockHandle, buffer,strlen(buffer));
snprintf(buffer,1024,"Content-Length: %d\r\n", strlen(data)); snprintf(buffer,1024,"Content-Length: %d\r\n", (int)strlen(data));
ANETwrite(pHttp->sockHandle, buffer,strlen(buffer)); ANETwrite(pHttp->sockHandle, buffer,strlen(buffer));
sendAuth(pHttp); sendAuth(pHttp);
ANETwrite(pHttp->sockHandle,data,strlen(data)); ANETwrite(pHttp->sockHandle,data,strlen(data));