- ascon.c: bug fix

- binprot.c: enhancements
- devser.c, scriptcontext.c: introduced specifiaction of start time in poll
This commit is contained in:
2017-04-07 10:10:10 +02:00
parent c4cee85b57
commit 10cb44df85
5 changed files with 286 additions and 100 deletions

20
ascon.c
View File

@ -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)

252
binprot.c
View File

@ -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; return -1;
}
} else { } else {
return -1; 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 {

View File

@ -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; double p; /* phase */
/* nextTime gives the next possible time according to the
* following rules: if (interval <= 0) return now;
* (1) result > now if (now < due) return due;
* (2) result is a multiple of interval
* (3) result >= due OR result >= due - lastInterval + interval p = round(fmod(due, interval)*1e6)/1e6;
*/ return p + interval * floor((due-p)/interval + (now-due)/interval + 1.000001);
if (interval > lastInterval) {
base = due - lastInterval * 0.01;
} else {
base = due - lastInterval + interval * 0.99;
}
if (now > base) {
base = now;
}
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);
} }
StartAscon(devser);
devser->status = AsconTask(devser->ascon);
while (action != NULL) { while (action != NULL) {
StartAscon(devser);
devser->status = AsconTask(devser->ascon);
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");

View File

@ -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)
{ {

View File

@ -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);
@ -551,7 +554,7 @@ static char *SctActionHandler(void *actionData, char *lastReply,
l = blank - origScript; l = blank - origScript;
} else { } else {
l = strlen(origScript); l = strlen(origScript);
} }
snprintf(eprop, sizeof eprop, "error_in_%.*s", (int)l, origScript); snprintf(eprop, sizeof eprop, "error_in_%.*s", (int)l, origScript);
emsg = GetHdbProp(node, eprop); emsg = GetHdbProp(node, eprop);
cnt = 0; cnt = 0;
@ -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));