- ascon.c: bug fix
- binprot.c: enhancements - devser.c, scriptcontext.c: introduced specifiaction of start time in poll
This commit is contained in:
8
ascon.c
8
ascon.c
@ -284,14 +284,15 @@ int AsconWriteChars(int fd, char *data, int length)
|
|||||||
|
|
||||||
if (length <= 0)
|
if (length <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
/*
|
|
||||||
{ int i;
|
/* { int i;
|
||||||
for (i=0; i<length; i++) {
|
for (i=0; i<length; i++) {
|
||||||
PrintChar(data[i]);
|
PrintChar(data[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("<written\n");
|
printf("<written\n");
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FD_ZERO(&wmask);
|
FD_ZERO(&wmask);
|
||||||
FD_SET(fd, &wmask);
|
FD_SET(fd, &wmask);
|
||||||
ret = uselect(fd + 1, NULL, &wmask, NULL, &tmo);
|
ret = uselect(fd + 1, NULL, &wmask, NULL, &tmo);
|
||||||
@ -814,8 +815,7 @@ int AsconWrite(Ascon * a, char *command, int noResponse)
|
|||||||
a->noResponse = noResponse;
|
a->noResponse = noResponse;
|
||||||
a->state = AsconWriteStart;
|
a->state = AsconWriteStart;
|
||||||
a->responseValid = 0;
|
a->responseValid = 0;
|
||||||
AsconTask(a);
|
return AsconTask(a);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *AsconRead(Ascon * a)
|
char *AsconRead(Ascon * a)
|
||||||
|
250
binprot.c
250
binprot.c
@ -22,8 +22,18 @@
|
|||||||
* a number converted according to the choosen format, i1 is default
|
* a number converted according to the choosen format, i1 is default
|
||||||
* int<n> changing the format to <n> byte integers
|
* int<n> changing the format to <n> byte integers
|
||||||
* hex changing the format to hexadecimal (1 byte at a time)
|
* hex changing the format to hexadecimal (1 byte at a time)
|
||||||
* float changing the format to 4 byte ieee float
|
* float<o> changing the format to 4 byte ieee float
|
||||||
* crc send crc
|
* order <o>:
|
||||||
|
* 0: normal (may be omitted)
|
||||||
|
* 1: exchange bytes within words
|
||||||
|
* 2: exchange words
|
||||||
|
* 3: invert order
|
||||||
|
* str<n> string nul terminated or with exactly n characters
|
||||||
|
* (encode space by underscore)
|
||||||
|
* crc<t><i> send crc
|
||||||
|
* <t> is the type of crc
|
||||||
|
* (m: modbus, k: keller, r: rs_port, s: sycon, c: checksum)
|
||||||
|
* <i> index from where to start counting (default 0)
|
||||||
*
|
*
|
||||||
* and formatItem is one of the follwing
|
* and formatItem is one of the follwing
|
||||||
*
|
*
|
||||||
@ -38,11 +48,14 @@
|
|||||||
* if <n> is omitted, <n> = 1 is assumed
|
* if <n> is omitted, <n> = 1 is assumed
|
||||||
* hex convert 1 byte to hexadecimal coded integer
|
* hex convert 1 byte to hexadecimal coded integer
|
||||||
* and append it to the response
|
* and append it to the response
|
||||||
* float convert 4 bytes from ieee float
|
* float<o> convert 4 bytes from ieee float (<o> see above)
|
||||||
* and append the number to the response
|
* str<n> string (length n or nul terminated)
|
||||||
|
* (spaces are encoded by underscore)
|
||||||
* dump read all bytes in read buffer as hex (only for tests)
|
* dump read all bytes in read buffer as hex (only for tests)
|
||||||
* crc check crc (if wrong, "badCRC" is added to the response)
|
* crc<t><i> check crc (if wrong, "badCRC" is added to the response)
|
||||||
*
|
* <t> is the type of crc
|
||||||
|
* (m: modbus, k: keller, r: rs_port, s: sycon, c: checksum)
|
||||||
|
* <i> index from where to start counting (default 0)
|
||||||
* multiple items in the response are space separated
|
* multiple items in the response are space separated
|
||||||
*
|
*
|
||||||
* Usage example: Modbus read (float)
|
* Usage example: Modbus read (float)
|
||||||
@ -58,25 +71,50 @@
|
|||||||
* chksum-crc: simple 8bit checksum
|
* chksum-crc: simple 8bit checksum
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef enum {intType, hexType, floatType, skipType, codeType, checkType,
|
typedef enum {intType, hexType, floatType, strType,
|
||||||
crcType, dumpType, endType, errorType} BinDataType;
|
skipType, codeType, checkType, crcType,
|
||||||
// dumpType, endType, errorType must be the last items
|
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;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
CrcAlgorithm crcAlgorithm;
|
CrcAlgorithm crcAlgorithm;
|
||||||
|
CrcAlgorithm algo;
|
||||||
|
int crcStart;
|
||||||
pDynString inp;
|
pDynString inp;
|
||||||
char *nextFmt; // position of next format token
|
char *nextFmt; // position of next format token
|
||||||
pDynString result;
|
pDynString result;
|
||||||
int expectedChars;
|
int expectedChars;
|
||||||
BinDataType type;
|
BinDataType type;
|
||||||
|
int order;
|
||||||
|
int done;
|
||||||
long iValue;
|
long iValue;
|
||||||
int dumpFrom;
|
int dumpFrom;
|
||||||
int syconState;
|
int syconState;
|
||||||
unsigned char chksum;
|
unsigned char chksum;
|
||||||
|
pDynString data;
|
||||||
} BinPrivate;
|
} BinPrivate;
|
||||||
|
|
||||||
|
#define MAXDUMP 999
|
||||||
|
#define NUL_TERMINATED 9999
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
static int parseAlgo(char *inp, BinPrivate *p) {
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
p->algo = p->crcAlgorithm;
|
||||||
|
switch (*inp) {
|
||||||
|
case 'm': p->algo = modbusCrc; break;
|
||||||
|
case 'k': p->algo = kellerCrc; break;
|
||||||
|
case 'r': p->algo = rsportCrc; break;
|
||||||
|
case 's': p->algo = syconCrc; break;
|
||||||
|
case 'c': p->algo = chksumCrc; break;
|
||||||
|
}
|
||||||
|
while (*inp > '9') inp++;
|
||||||
|
sscanf(inp, "%d", &index);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
static int calc_crc(char *inp, int inpLen)
|
static int calc_crc(char *inp, int inpLen)
|
||||||
{
|
{
|
||||||
@ -156,25 +194,66 @@ static int calc_chksum(char *inp, int inpLen)
|
|||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
int BinGetItem(char *str, char *item, size_t item_size) {
|
||||||
|
int cntcurly = 0;
|
||||||
|
char *p, *res;
|
||||||
|
int l;
|
||||||
|
|
||||||
|
p = str;
|
||||||
|
while (*p == ' ') p++;
|
||||||
|
if (*p == '{') {
|
||||||
|
cntcurly++;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
if (!*p) return -1;
|
||||||
|
res = p;
|
||||||
|
while (*p) {
|
||||||
|
if (*p == '{') {
|
||||||
|
cntcurly++;
|
||||||
|
} else if (*p == '}') {
|
||||||
|
cntcurly--;
|
||||||
|
if (cntcurly == 0) {
|
||||||
|
l = p - str - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (*p == ' ' && cntcurly == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
l = p - res;
|
||||||
|
if (l >= item_size) {
|
||||||
|
l = item_size - 1;
|
||||||
|
}
|
||||||
|
strncpy(item, res, l);
|
||||||
|
item[l] = '\0';
|
||||||
|
return p - str;
|
||||||
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
int BinReadItem(Ascon *a) {
|
int BinReadItem(Ascon *a) {
|
||||||
BinPrivate *p = a->private;
|
BinPrivate *p = a->private;
|
||||||
char item[32];
|
char item[32];
|
||||||
int valen;
|
int valen;
|
||||||
int size;
|
int size;
|
||||||
|
CrcAlgorithm algo;
|
||||||
|
|
||||||
if (sscanf(p->nextFmt, "%30s%n", item, &valen) <= 0) {
|
valen = BinGetItem(p->nextFmt, item, sizeof item);
|
||||||
|
if (valen < 0) {
|
||||||
if (p->type < dumpType) {
|
if (p->type < dumpType) {
|
||||||
p->dumpFrom = GetDynStringLength(a->rdBuffer);
|
p->dumpFrom = GetDynStringLength(a->rdBuffer);
|
||||||
p->type = endType;
|
p->type = endType;
|
||||||
}
|
}
|
||||||
p->expectedChars = 999;
|
p->expectedChars = MAXDUMP;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcasecmp(item, "crc") == 0) {
|
if (strncasecmp(item, "crc", 3) == 0) {
|
||||||
p->type = crcType;
|
p->type = crcType;
|
||||||
if (p->crcAlgorithm == chksumCrc) {
|
p->expectedChars = 2;
|
||||||
|
p->crcStart = parseAlgo(item + 3, p);
|
||||||
|
if (p->algo == chksumCrc) {
|
||||||
p->expectedChars = 1;
|
p->expectedChars = 1;
|
||||||
} else {
|
} else {
|
||||||
p->expectedChars = 2;
|
p->expectedChars = 2;
|
||||||
@ -187,9 +266,22 @@ int BinReadItem(Ascon *a) {
|
|||||||
p->expectedChars = size;
|
p->expectedChars = size;
|
||||||
p->type = intType;
|
p->type = intType;
|
||||||
p->iValue = 0;
|
p->iValue = 0;
|
||||||
} else if (strcasecmp(item, "float") == 0) {
|
} else if (strncasecmp(item, "float", 5) == 0) {
|
||||||
|
p->order = 0;
|
||||||
|
sscanf(item + 5, "%d", &p->order);
|
||||||
p->expectedChars = 4;
|
p->expectedChars = 4;
|
||||||
p->type = floatType;
|
p->type = floatType;
|
||||||
|
DynStringClear(p->data);
|
||||||
|
} else if (strncasecmp(item, "str", 3) == 0) {
|
||||||
|
size = 1;
|
||||||
|
sscanf(item + 3, "%d", &size);
|
||||||
|
if (size == 0) {
|
||||||
|
size = NUL_TERMINATED;
|
||||||
|
}
|
||||||
|
p->expectedChars = size;
|
||||||
|
p->type = strType;
|
||||||
|
p->done = 0;
|
||||||
|
DynStringClear(p->data);
|
||||||
} else if (strcasecmp(item, "hex") == 0) {
|
} else if (strcasecmp(item, "hex") == 0) {
|
||||||
p->expectedChars = 1;
|
p->expectedChars = 1;
|
||||||
p->type = hexType;
|
p->type = hexType;
|
||||||
@ -205,12 +297,17 @@ int BinReadItem(Ascon *a) {
|
|||||||
p->type = skipType;
|
p->type = skipType;
|
||||||
} else {
|
} else {
|
||||||
p->iValue = 0;
|
p->iValue = 0;
|
||||||
if (1 == sscanf(item, "%ld", &p->iValue)) {
|
if (strncasecmp(item, "0x", 2) == 0) {
|
||||||
p->expectedChars = 1;
|
if (1 != sscanf(item + 2, "%lx", &p->iValue)) {
|
||||||
p->type = checkType;
|
|
||||||
} else {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (1 != sscanf(item, "%ld", &p->iValue)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p->expectedChars = 1;
|
||||||
|
p->type = checkType;
|
||||||
}
|
}
|
||||||
p->nextFmt += valen;
|
p->nextFmt += valen;
|
||||||
return 1;
|
return 1;
|
||||||
@ -265,17 +362,39 @@ void BinToSycon(pDynString dyn) {
|
|||||||
free(str);
|
free(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
void BinShuffle(char *input, int order) {
|
||||||
|
/* order may be 0: no shuffle, 1: change within words, 2: change words, 3: invert*/
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
switch (order) {
|
||||||
|
case 1:
|
||||||
|
ch = input[0]; input[0] = input[1]; input[1] = ch;
|
||||||
|
ch = input[2]; input[2] = input[3]; input[3] = ch;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ch = input[0]; input[0] = input[2]; input[2] = ch;
|
||||||
|
ch = input[1]; input[1] = input[3]; input[3] = ch;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
ch = input[0]; input[0] = input[3]; input[3] = ch;
|
||||||
|
ch = input[1]; input[1] = input[2]; input[2] = ch;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
int BinHandler(Ascon *a) {
|
int BinHandler(Ascon *a) {
|
||||||
int res;
|
int res;
|
||||||
char *str;
|
char *str;
|
||||||
int len;
|
int len;
|
||||||
int i, l, pos;
|
int i, l, ls, pos;
|
||||||
|
int start;
|
||||||
unsigned int crc;
|
unsigned int crc;
|
||||||
pDynString dyn;
|
pDynString dyn;
|
||||||
char item[32];
|
char item[32];
|
||||||
char data[8];
|
char data[8];
|
||||||
int size;
|
int size;
|
||||||
|
int order;
|
||||||
int valen;
|
int valen;
|
||||||
BinDataType type;
|
BinDataType type;
|
||||||
long iValue;
|
long iValue;
|
||||||
@ -293,44 +412,52 @@ int BinHandler(Ascon *a) {
|
|||||||
str = GetCharArray(p->inp);
|
str = GetCharArray(p->inp);
|
||||||
len = GetDynStringLength(p->inp);
|
len = GetDynStringLength(p->inp);
|
||||||
l = 0;
|
l = 0;
|
||||||
size = 1;
|
|
||||||
type = intType;
|
type = intType;
|
||||||
for (pos = 0; pos < len; ) {
|
for (pos = 0; pos < len; ) {
|
||||||
if (sscanf(str + pos, "%30s%n", item, &valen) <= 0) {
|
valen = BinGetItem(str + pos, item, sizeof item);
|
||||||
|
if (valen < 0) {
|
||||||
BinError(a, "missing '/'");
|
BinError(a, "missing '/'");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
pos += valen;
|
pos += valen;
|
||||||
if (strcasecmp(item, "/") == 0) {
|
if (strcasecmp(item, "/") == 0) {
|
||||||
break;
|
break;
|
||||||
} else if (strcasecmp(item, "crc") == 0) {
|
} else if (strncasecmp(item, "crc", 3) == 0) {
|
||||||
switch (p->crcAlgorithm) {
|
start = parseAlgo(item + 3, p);
|
||||||
|
switch (p->algo) {
|
||||||
case kellerCrc:
|
case kellerCrc:
|
||||||
crc = calc_crc(GetCharArray(dyn), l);
|
crc = calc_crc(GetCharArray(dyn)+start, l-start);
|
||||||
DynStringConcatChar(dyn, crc / 256);
|
DynStringConcatChar(dyn, crc / 256);
|
||||||
DynStringConcatChar(dyn, crc % 256);
|
DynStringConcatChar(dyn, crc % 256);
|
||||||
break;
|
break;
|
||||||
case modbusCrc:
|
case modbusCrc:
|
||||||
crc = calc_crc(GetCharArray(dyn), l);
|
crc = calc_crc(GetCharArray(dyn)+start, l-start);
|
||||||
DynStringConcatChar(dyn, crc % 256);
|
DynStringConcatChar(dyn, crc % 256);
|
||||||
DynStringConcatChar(dyn, crc / 256);
|
DynStringConcatChar(dyn, crc / 256);
|
||||||
break;
|
break;
|
||||||
case chksumCrc:
|
case chksumCrc:
|
||||||
crc = calc_chksum(GetCharArray(dyn), l);
|
crc = calc_chksum(GetCharArray(dyn)+start, l-start);
|
||||||
DynStringConcatChar(dyn, crc % 256);
|
DynStringConcatChar(dyn, crc % 256);
|
||||||
break;
|
break;
|
||||||
case rsportCrc:
|
case rsportCrc:
|
||||||
crc = calc_crc8(GetCharArray(dyn), l);
|
crc = calc_crc8(GetCharArray(dyn)+start, l-start);
|
||||||
DynStringConcatChar(dyn, crc);
|
DynStringConcatChar(dyn, crc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (strncasecmp(item, "int", 3) == 0) {
|
} else if (strncasecmp(item, "int", 3) == 0) {
|
||||||
|
size = 1;
|
||||||
sscanf(item + 3, "%d", &size);
|
sscanf(item + 3, "%d", &size);
|
||||||
type = intType;
|
type = intType;
|
||||||
} else if (strcasecmp(item, "hex") == 0) {
|
} else if (strcasecmp(item, "hex") == 0) {
|
||||||
type = hexType;
|
type = hexType;
|
||||||
} else if (strcasecmp(item, "float") == 0) {
|
} else if (strncasecmp(item, "float", 5) == 0) {
|
||||||
|
order = 0;
|
||||||
|
sscanf(item + 5, "%d", &order);
|
||||||
type = floatType;
|
type = floatType;
|
||||||
|
} else if (strncasecmp(item, "str", 3) == 0) {
|
||||||
|
size = NUL_TERMINATED;
|
||||||
|
sscanf(item + 3, "%d", &size);
|
||||||
|
type = strType;
|
||||||
} else {
|
} else {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case intType:
|
case intType:
|
||||||
@ -339,6 +466,9 @@ int BinHandler(Ascon *a) {
|
|||||||
BinError(a, "invalid integer");
|
BinError(a, "invalid integer");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
if (iValue < 0) {
|
||||||
|
printf("%ld\n", iValue);
|
||||||
|
}
|
||||||
uValue = iValue;
|
uValue = iValue;
|
||||||
for (i = size - 1; i >= 0; i--) {
|
for (i = size - 1; i >= 0; i--) {
|
||||||
if (i < sizeof data) {
|
if (i < sizeof data) {
|
||||||
@ -362,6 +492,7 @@ int BinHandler(Ascon *a) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
DynStringConcatChar(dyn, (iValue & 255));
|
DynStringConcatChar(dyn, (iValue & 255));
|
||||||
|
l += 1;
|
||||||
break;
|
break;
|
||||||
case floatType:
|
case floatType:
|
||||||
res = sscanf(item, "%lf", &fValue);
|
res = sscanf(item, "%lf", &fValue);
|
||||||
@ -370,12 +501,26 @@ int BinHandler(Ascon *a) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
double2ieee(fValue, data);
|
double2ieee(fValue, data);
|
||||||
DynStringConcatChar(dyn, data[0]);
|
BinShuffle(data, order);
|
||||||
DynStringConcatChar(dyn, data[1]);
|
DynStringConcatBytes(dyn, data, 4);
|
||||||
DynStringConcatChar(dyn, data[2]);
|
|
||||||
DynStringConcatChar(dyn, data[3]);
|
|
||||||
l += 4;
|
l += 4;
|
||||||
break;
|
break;
|
||||||
|
case strType:
|
||||||
|
ls = strlen(item);
|
||||||
|
if (ls > size) {
|
||||||
|
item[size] = '\0';
|
||||||
|
}
|
||||||
|
DynStringConcat(dyn, item);
|
||||||
|
if (size == NUL_TERMINATED) {
|
||||||
|
DynStringConcatChar(dyn, 0);
|
||||||
|
l += ls + 1;
|
||||||
|
} else {
|
||||||
|
for (i = ls; i < size; i++) {
|
||||||
|
DynStringConcatChar(dyn, 0);
|
||||||
|
}
|
||||||
|
l += size;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -530,21 +675,42 @@ int BinHandler(Ascon *a) {
|
|||||||
DynStringConcat(p->result, item);
|
DynStringConcat(p->result, item);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case floatType: /* does not work with sycon when stuffed */
|
case floatType:
|
||||||
p->expectedChars--;
|
p->expectedChars--;
|
||||||
|
DynStringConcatChar(p->data, a->lastChar);
|
||||||
if (p->expectedChars <= 0) {
|
if (p->expectedChars <= 0) {
|
||||||
str = GetCharArray(a->rdBuffer) + GetDynStringLength(a->rdBuffer) - 4;
|
char *shuffle = GetCharArray(p->data);
|
||||||
fValue = ieee2double(str);
|
BinShuffle(shuffle, p->order);
|
||||||
|
fValue = ieee2double(shuffle);
|
||||||
snprintf(item, sizeof item, "%.7g ", fValue);
|
snprintf(item, sizeof item, "%.7g ", fValue);
|
||||||
DynStringConcat(p->result, item);
|
DynStringConcat(p->result, item);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case strType:
|
||||||
|
if (a->lastChar) {
|
||||||
|
if (!p->done) {
|
||||||
|
DynStringConcatChar(p->data, a->lastChar);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p->done = 1;
|
||||||
|
if (p->expectedChars == NUL_TERMINATED) {
|
||||||
|
DynStringConcat(p->result, GetCharArray(p->data));
|
||||||
|
p->expectedChars = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p->expectedChars--;
|
||||||
|
if (p->expectedChars <= 0) {
|
||||||
|
DynStringConcat(p->result, GetCharArray(p->data));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case crcType:
|
case crcType:
|
||||||
p->expectedChars--;
|
p->expectedChars--;
|
||||||
if (p->expectedChars <= 0) {
|
if (p->expectedChars <= 0) {
|
||||||
str = GetCharArray(a->rdBuffer);
|
str = GetCharArray(a->rdBuffer);
|
||||||
l = GetDynStringLength(a->rdBuffer);
|
l = GetDynStringLength(a->rdBuffer);
|
||||||
switch (p->crcAlgorithm) {
|
switch (p->algo) {
|
||||||
case syconCrc: /* ignore crc check */
|
case syconCrc: /* ignore crc check */
|
||||||
/* subtract CRC char (undo the addition) and subtract crc higher four bits */
|
/* subtract CRC char (undo the addition) and subtract crc higher four bits */
|
||||||
p->chksum -= a->lastChar + (a->lastChar & 0x0f);
|
p->chksum -= a->lastChar + (a->lastChar & 0x0f);
|
||||||
@ -554,7 +720,7 @@ int BinHandler(Ascon *a) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case chksumCrc:
|
case chksumCrc:
|
||||||
if (calc_chksum(str, l-1) != (unsigned char)str[l-1]) {
|
if (calc_chksum(str+p->crcStart, l-1-p->crcStart) != (unsigned char)str[l-1]) {
|
||||||
DynStringConcat(p->result, "badCRC ");
|
DynStringConcat(p->result, "badCRC ");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -565,7 +731,7 @@ int BinHandler(Ascon *a) {
|
|||||||
/* fall through */
|
/* fall through */
|
||||||
case modbusCrc:
|
case modbusCrc:
|
||||||
case rsportCrc:
|
case rsportCrc:
|
||||||
if (calc_crc(str, l) != 0) {
|
if (calc_crc(str+p->crcStart, l-p->crcStart) != 0) {
|
||||||
DynStringConcat(p->result, "badCRC ");
|
DynStringConcat(p->result, "badCRC ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -576,8 +742,10 @@ int BinHandler(Ascon *a) {
|
|||||||
break;
|
break;
|
||||||
case checkType:
|
case checkType:
|
||||||
p->expectedChars--;
|
p->expectedChars--;
|
||||||
if ((a->lastChar & 255) != p->iValue) {
|
if ((unsigned char)a->lastChar != p->iValue) {
|
||||||
DynStringCopy(a->errmsg, "BINERR: mismatch ");
|
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);
|
||||||
|
DynStringCopy(a->errmsg, item);
|
||||||
p->type = errorType;
|
p->type = errorType;
|
||||||
p->dumpFrom = 0;
|
p->dumpFrom = 0;
|
||||||
/* skip to end */
|
/* skip to end */
|
||||||
@ -596,6 +764,7 @@ static void BinPrivateKill(void *pVoid) {
|
|||||||
BinPrivate *p = pVoid;
|
BinPrivate *p = pVoid;
|
||||||
DeleteDynString(p->inp);
|
DeleteDynString(p->inp);
|
||||||
DeleteDynString(p->result);
|
DeleteDynString(p->result);
|
||||||
|
DeleteDynString(p->data);
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -631,6 +800,7 @@ static int BinInit(Ascon * a, SConnection * con, int argc, char *argv[])
|
|||||||
a->hostport = strdup(argv[1]);
|
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);
|
||||||
|
p->data = CreateDynString(60,63);
|
||||||
if (argc > 3) {
|
if (argc > 3) {
|
||||||
a->timeout = atof(argv[3]);
|
a->timeout = atof(argv[3]);
|
||||||
} else {
|
} else {
|
||||||
|
71
devser.c
71
devser.c
@ -76,26 +76,17 @@ static void DevFreeActionList(DevAction * actions)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static double nextTime(double due,
|
static double nextDue(double due, double now, double interval) {
|
||||||
double lastInterval,
|
/* calculate next due value. the phase is rounded to usec in order to
|
||||||
double now,
|
prevent phase drifts by summed rounding errors
|
||||||
double interval) {
|
|
||||||
double base;
|
|
||||||
/* nextTime gives the next possible time according to the
|
|
||||||
* following rules:
|
|
||||||
* (1) result > now
|
|
||||||
* (2) result is a multiple of interval
|
|
||||||
* (3) result >= due OR result >= due - lastInterval + interval
|
|
||||||
*/
|
*/
|
||||||
if (interval > lastInterval) {
|
double p; /* phase */
|
||||||
base = due - lastInterval * 0.01;
|
|
||||||
} else {
|
if (interval <= 0) return now;
|
||||||
base = due - lastInterval + interval * 0.99;
|
if (now < due) return due;
|
||||||
}
|
|
||||||
if (now > base) {
|
p = round(fmod(due, interval)*1e6)/1e6;
|
||||||
base = now;
|
return p + interval * floor((due-p)/interval + (now-due)/interval + 1.000001);
|
||||||
}
|
|
||||||
return (floor(base / interval) + 1) * interval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -124,7 +115,7 @@ static DevAction *DevNextAction(DevSer * devser)
|
|||||||
action->timeDue = now;
|
action->timeDue = now;
|
||||||
} else {
|
} else {
|
||||||
/* increase timeDue according to interval */
|
/* increase timeDue according to interval */
|
||||||
action->timeDue = nextTime(0, 0, now, action->interval);
|
action->timeDue = nextDue(action->timeDue, now, action->interval);
|
||||||
}
|
}
|
||||||
prio = action->prio;
|
prio = action->prio;
|
||||||
|
|
||||||
@ -243,9 +234,9 @@ int DevQueueTask(void *ds)
|
|||||||
action = DevNextAction(devser);
|
action = DevNextAction(devser);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (action != NULL) {
|
|
||||||
StartAscon(devser);
|
StartAscon(devser);
|
||||||
devser->status = AsconTask(devser->ascon);
|
devser->status = AsconTask(devser->ascon);
|
||||||
|
while (action != NULL) {
|
||||||
AsconLog(devser);
|
AsconLog(devser);
|
||||||
if (devser->status >= AsconFailure) {
|
if (devser->status >= AsconFailure) {
|
||||||
replyData = AsconGetError(devser->ascon);
|
replyData = AsconGetError(devser->ascon);
|
||||||
@ -272,7 +263,11 @@ int DevQueueTask(void *ds)
|
|||||||
}
|
}
|
||||||
sendData = action->hdl(action->data, replyData, (devser->status != AsconReady));
|
sendData = action->hdl(action->data, replyData, (devser->status != AsconReady));
|
||||||
if (sendData != NULL) {
|
if (sendData != NULL) {
|
||||||
AsconWrite(devser->ascon, sendData, 0);
|
devser->status = AsconWrite(devser->ascon, sendData, 0);
|
||||||
|
if (devser->status >= AsconFailure) {
|
||||||
|
replyData = AsconGetError(devser->ascon);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
LogStart(devser);
|
LogStart(devser);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -284,6 +279,8 @@ int DevQueueTask(void *ds)
|
|||||||
devser->current = NULL;
|
devser->current = NULL;
|
||||||
}
|
}
|
||||||
action = DevNextAction(devser);
|
action = DevNextAction(devser);
|
||||||
|
StartAscon(devser);
|
||||||
|
devser->status = AsconTask(devser->ascon);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -391,8 +388,8 @@ int DevUnschedule(DevSer * devser, void *callData,
|
|||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DevSchedule(DevSer * devser, void *actionData,
|
int DevScheduleS(DevSer * devser, void *actionData,
|
||||||
DevPrio prio, double interval,
|
DevPrio prio, double interval, double start,
|
||||||
DevActionHandler * hdl, DevActionMatch * matchFunc,
|
DevActionHandler * hdl, DevActionMatch * matchFunc,
|
||||||
DevKillActionData * killFunc, DevInfoFunc * infoFunc)
|
DevKillActionData * killFunc, DevInfoFunc * infoFunc)
|
||||||
{
|
{
|
||||||
@ -454,6 +451,7 @@ int DevSchedule(DevSer * devser, void *actionData,
|
|||||||
action->kill = killFunc;
|
action->kill = killFunc;
|
||||||
action->infoFunc = infoFunc;
|
action->infoFunc = infoFunc;
|
||||||
action->timeDue = 0;
|
action->timeDue = 0;
|
||||||
|
action->interval = 0;
|
||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,22 +466,31 @@ int DevSchedule(DevSer * devser, void *actionData,
|
|||||||
if (interval < 0) { /* case "queued" */
|
if (interval < 0) { /* case "queued" */
|
||||||
action->interval = -1.0;
|
action->interval = -1.0;
|
||||||
} else { /* case "scheduled" */
|
} else { /* case "scheduled" */
|
||||||
if (action->timeDue == 0) { /* not yet scheduled: do it immediately */
|
/* nextDue calculates the next due date after the last call
|
||||||
action->timeDue = DoubleTime();
|
however, it returns the 'start' value
|
||||||
} else { /* calculate next time */
|
- when this is a new action and start > 0
|
||||||
action->timeDue = nextTime(action->timeDue, action->interval,
|
- when the presumed last call time is bigger the 'start' value
|
||||||
DoubleTime(), interval);
|
*/
|
||||||
}
|
action->timeDue = nextDue(start, action->timeDue - action->interval, interval);
|
||||||
action->interval = interval;
|
action->interval = interval;
|
||||||
}
|
}
|
||||||
return ret; /* when 0, actionData was killed */
|
return ret; /* when 0, actionData was killed */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DevSchedule(DevSer * devser, void *actionData,
|
||||||
|
DevPrio prio, double interval,
|
||||||
|
DevActionHandler * hdl, DevActionMatch * matchFunc,
|
||||||
|
DevKillActionData * killFunc, DevInfoFunc * infoFunc)
|
||||||
|
{
|
||||||
|
return DevScheduleS(devser, actionData, prio, interval, 0.0,
|
||||||
|
hdl, matchFunc, killFunc, infoFunc);
|
||||||
|
}
|
||||||
|
|
||||||
int DevQueue(DevSer * devser, void *actionData, DevPrio prio,
|
int DevQueue(DevSer * devser, void *actionData, DevPrio prio,
|
||||||
DevActionHandler * hdl, DevActionMatch * matchFunc,
|
DevActionHandler * hdl, DevActionMatch * matchFunc,
|
||||||
DevKillActionData * killFunc, DevInfoFunc *infoFunc)
|
DevKillActionData * killFunc, DevInfoFunc *infoFunc)
|
||||||
{
|
{
|
||||||
return DevSchedule(devser, actionData, prio, -1.0, hdl
|
return DevScheduleS(devser, actionData, prio, -1.0, 0.0, hdl
|
||||||
, matchFunc, killFunc, infoFunc);
|
, matchFunc, killFunc, infoFunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,7 +566,7 @@ char * DevList(DevSer * devser) {
|
|||||||
DynStringConcat(result, str);
|
DynStringConcat(result, str);
|
||||||
free(str);
|
free(str);
|
||||||
} else {
|
} else {
|
||||||
snprintf(text, sizeof text, "%8.8lx", (unsigned long)action->data);
|
snprintf(text, sizeof text, "%p", action->data);
|
||||||
DynStringConcat(result, text);
|
DynStringConcat(result, text);
|
||||||
}
|
}
|
||||||
DynStringConcat(result, "\n");
|
DynStringConcat(result, "\n");
|
||||||
|
3
logger.c
3
logger.c
@ -1,5 +1,5 @@
|
|||||||
/*---------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------
|
||||||
Logger.c
|
logger.c
|
||||||
|
|
||||||
Markus Zolliker, Sept 2004
|
Markus Zolliker, Sept 2004
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
@ -20,6 +20,7 @@ static Logger *list;
|
|||||||
static time_t lastLife = 0;
|
static time_t lastLife = 0;
|
||||||
static time_t lastWritten = 0;
|
static time_t lastWritten = 0;
|
||||||
static time_t omitCheck = 0;
|
static time_t omitCheck = 0;
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
char *LoggerName(Logger * log)
|
char *LoggerName(Logger * log)
|
||||||
{
|
{
|
||||||
|
@ -338,13 +338,16 @@ int SctCallInContext(SConnection * con, char *script, Hdb * node,
|
|||||||
char *result = NULL;
|
char *result = NULL;
|
||||||
int iRet = 1;
|
int iRet = 1;
|
||||||
int verbose = controller->verbose;
|
int verbose = controller->verbose;
|
||||||
|
char path[MAX_HDB_PATH];
|
||||||
|
|
||||||
PushContext(node, controller);
|
PushContext(node, controller);
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
SCPrintf(con, eLog, "%6.3f script: %s", secondsOfMinute(), script);
|
GetHdbPath(node, path, sizeof path);
|
||||||
|
SCPrintf(con, eLog, "%6.3f script: (on %s) %s", secondsOfMinute(), path, script);
|
||||||
}
|
}
|
||||||
if (controller->fd != NULL) {
|
if (controller->fd != NULL) {
|
||||||
fprintf(controller->fd,"%6.3f script: %s\n", secondsOfMinute(), script);
|
GetHdbPath(node, path, sizeof path);
|
||||||
|
fprintf(controller->fd,"%6.3f script: (on %s) %s\n", secondsOfMinute(), path, script);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroPush(con);
|
MacroPush(con);
|
||||||
@ -877,12 +880,13 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData,
|
|||||||
* solution is to requeue the node.
|
* solution is to requeue the node.
|
||||||
*/
|
*/
|
||||||
SCDeleteConnection(data->conCtx);
|
SCDeleteConnection(data->conCtx);
|
||||||
|
} else {
|
||||||
|
data->syncid = SyncedIncr(0);
|
||||||
}
|
}
|
||||||
data->conCtx = SCCopyConnection(con);
|
data->conCtx = SCCopyConnection(con);
|
||||||
data->answered = 0;
|
data->answered = 0;
|
||||||
data->inMacro = SCinMacro(con);
|
data->inMacro = SCinMacro(con);
|
||||||
tracePar(node->name,"Queued %s to %s",node->name, GetCharArray(text));
|
tracePar(node->name,"Queued %s to %s",node->name, GetCharArray(text));
|
||||||
data->syncid = SyncedIncr(0);
|
|
||||||
data->busy = 1;
|
data->busy = 1;
|
||||||
DevQueue(data->controller->devser, data, prio,
|
DevQueue(data->controller->devser, data, prio,
|
||||||
SctWriteHandler, SctMatch, SctEndData, SctDataInfo);
|
SctWriteHandler, SctMatch, SctEndData, SctDataInfo);
|
||||||
@ -980,7 +984,7 @@ static void SctKillCBData(void *d)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int SctAddPollNode(SctController * controller, Hdb * node, double interval,
|
int SctAddPollNode(SctController * controller, Hdb * node, double interval,
|
||||||
DevPrio prio, char *action)
|
double start, DevPrio prio, char *action)
|
||||||
{
|
{
|
||||||
SctData *data;
|
SctData *data;
|
||||||
hdbCallback *cb;
|
hdbCallback *cb;
|
||||||
@ -1003,7 +1007,7 @@ int SctAddPollNode(SctController * controller, Hdb * node, double interval,
|
|||||||
data->name = strdup(action);
|
data->name = strdup(action);
|
||||||
|
|
||||||
data->syncid = SyncedIncr(0);
|
data->syncid = SyncedIncr(0);
|
||||||
if (DevSchedule(controller->devser, data, prio, interval,
|
if (DevScheduleS(controller->devser, data, prio, interval, start,
|
||||||
SctActionHandler, SctMatch, SctKillData, SctDataInfo)) {
|
SctActionHandler, SctMatch, SctKillData, SctDataInfo)) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
@ -1016,15 +1020,17 @@ static int SctPollCmd(pSICSOBJ ccmd, SConnection * con,
|
|||||||
{
|
{
|
||||||
Hdb *node;
|
Hdb *node;
|
||||||
SctController *controller;
|
SctController *controller;
|
||||||
double interval;
|
double interval, start;
|
||||||
char *path;
|
char *path;
|
||||||
DevPrio prio;
|
DevPrio prio;
|
||||||
char *action;
|
char *action;
|
||||||
char *prioText;
|
char *prioText;
|
||||||
|
char *intervalText;
|
||||||
|
int ii;
|
||||||
|
|
||||||
if (nPar < 1) {
|
if (nPar < 1) {
|
||||||
SCPrintf(con, eError,
|
SCPrintf(con, eError,
|
||||||
"ERROR: should be: %s poll <node> (<interval> <prio> <action>)",
|
"ERROR: should be: %s poll <node> (<interval> <prio> <action> <start>)",
|
||||||
ccmd->objectNode->name);
|
ccmd->objectNode->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1043,15 +1049,16 @@ static int SctPollCmd(pSICSOBJ ccmd, SConnection * con,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
action = ParText(cmdNode, "action", nPar, "read");
|
action = ParText(cmdNode, "action", nPar, "read");
|
||||||
|
start = ParValue(cmdNode, "start", nPar, 0.0);
|
||||||
|
|
||||||
if (SctAddPollNode(controller, node, interval, prio, action)) {
|
if (SctAddPollNode(controller, node, interval, start, prio, action)) {
|
||||||
SCPrintf(con, eValue,
|
SCPrintf(con, eValue,
|
||||||
"%s poll registered on %s (%g sec, %s prio)",
|
"%s poll registered on %s (%g sec, %s prio, %g start)",
|
||||||
action, path, interval, prioText);
|
action, path, interval, prioText, start);
|
||||||
} else {
|
} else {
|
||||||
SCPrintf(con, eValue,
|
SCPrintf(con, eValue,
|
||||||
"%s poll on %s changed to %g sec, %s prio",
|
"%s poll on %s changed to %g sec, %s prio, %g start",
|
||||||
action, path, interval, prioText);
|
action, path, interval, prioText, start);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1922,6 +1929,7 @@ static int SctMakeController(SConnection * con, SicsInterp * sics,
|
|||||||
AddSICSHdbPar(cmd, "interval", usMugger, MakeHdbFloat(5.0));
|
AddSICSHdbPar(cmd, "interval", usMugger, MakeHdbFloat(5.0));
|
||||||
AddSICSHdbPar(cmd, "prio", usMugger, MakeHdbText("read"));
|
AddSICSHdbPar(cmd, "prio", usMugger, MakeHdbText("read"));
|
||||||
AddSICSHdbPar(cmd, "action", usMugger, MakeHdbText("read"));
|
AddSICSHdbPar(cmd, "action", usMugger, MakeHdbText("read"));
|
||||||
|
AddSICSHdbPar(cmd, "start", usMugger, MakeHdbFloat(0.0));
|
||||||
|
|
||||||
cmd = AddSICSHdbPar(controller->node,
|
cmd = AddSICSHdbPar(controller->node,
|
||||||
"unpoll", usMugger, MakeSICSFunc(SctUnpollCmd));
|
"unpoll", usMugger, MakeSICSFunc(SctUnpollCmd));
|
||||||
|
Reference in New Issue
Block a user