Always return 0 from the AsconReading state to make sure we exit the AsconTask().
Since the PSI update the AsconTask() function will loop forever unless you return 0.
This commit is contained in:
@@ -280,37 +280,38 @@ static int aduLen = 0, RespLen = 0, pduLen = 0, DatLen = 0;
|
|||||||
static const int TIDidx=0, PIDidx=2, LENidx=4, UIDidx=6, CODEidx=7, DATLENidx=8, DATAidx=9;
|
static const int TIDidx=0, PIDidx=2, LENidx=4, UIDidx=6, CODEidx=7, DATLENidx=8, DATAidx=9;
|
||||||
static unsigned char ADU[ADUSIZE]; /* Allows upto 8 bytes if data */
|
static unsigned char ADU[ADUSIZE]; /* Allows upto 8 bytes if data */
|
||||||
int TCPMBReading(Ascon *a) {
|
int TCPMBReading(Ascon *a) {
|
||||||
const int MBAPLen = 7;
|
const int MBAPLen = 7, UIDpos=6;
|
||||||
int i, ret, rlen, byteCnt, allRead = 0;
|
int i, ret, rlen, byteCnt;
|
||||||
char chr, temp[64], errMsg[ERRLEN];
|
char chr, temp[64], errMsg[ERRLEN];
|
||||||
unsigned char ieee[4];
|
unsigned char ieee[4];
|
||||||
double dval;
|
double dval;
|
||||||
long int lival;
|
long int lival;
|
||||||
|
|
||||||
ret = AsconReadChar(a->fd, &chr);
|
ret = AsconReadChar(a->fd, &chr);
|
||||||
/* TODO Check for timeout while reading and call AsconError()
|
|
||||||
Eg if (DoubleTime() > a->lastReconnect + a->reconnectInterval) then AsconError
|
|
||||||
*/
|
|
||||||
while (ret > 0) {
|
while (ret > 0) {
|
||||||
a->start = DoubleTime();
|
a->start = DoubleTime();
|
||||||
ADU[aduLen++] = chr;
|
ADU[aduLen++] = chr;
|
||||||
ret = AsconReadChar(a->fd, &chr);
|
ret = AsconReadChar(a->fd, &chr);
|
||||||
}
|
}
|
||||||
if (ret < 0) {
|
|
||||||
AsconError(a, "AsconReadChar failed:", errno);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (RespLen == 0 && aduLen > CODEidx) {
|
if (RespLen == 0 && aduLen > CODEidx) {
|
||||||
RespLen = (ADU[LENidx] << 8) + ADU[LENidx+1];
|
RespLen = (ADU[LENidx] << 8) + ADU[LENidx+1];
|
||||||
}
|
}
|
||||||
if (allRead == 0 && aduLen >= (6 + RespLen)) {
|
|
||||||
/* all of response has been read */
|
if (aduLen < (UIDpos + RespLen)) {
|
||||||
/* FIXME If the Length field (ie RespLen) is wrong then we loop forever waiting for a response.
|
if (ret == 0) {
|
||||||
Can this be detected automatically (eg timeout) and reset?
|
if (a->timeout > 0) {
|
||||||
*/
|
if (DoubleTime() - a->start > a->timeout) {
|
||||||
allRead = 1;
|
AsconError(a, "read timeout", 0);
|
||||||
|
a->state = AsconTimeout;
|
||||||
}
|
}
|
||||||
if (allRead) {
|
}
|
||||||
|
} else if (ret < 0) {
|
||||||
|
AsconError(a, "AsconReadChar failed:", errno);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (ADU[CODEidx] > 0x80) {
|
if (ADU[CODEidx] > 0x80) {
|
||||||
a->state = AsconReadDone;
|
a->state = AsconReadDone;
|
||||||
snprintf(errMsg, ERRLEN, "TCPMODBUS: Function code %d exception %d:", ADU[CODEidx] & 0x0F, ADU[8] &0x0F);
|
snprintf(errMsg, ERRLEN, "TCPMODBUS: Function code %d exception %d:", ADU[CODEidx] & 0x0F, ADU[8] &0x0F);
|
||||||
@@ -395,17 +396,7 @@ int TCPMBReading(Ascon *a) {
|
|||||||
}
|
}
|
||||||
aduLen = 0, DatLen = 0, RespLen = 0;
|
aduLen = 0, DatLen = 0, RespLen = 0;
|
||||||
memset(ADU, 0, ADUSIZE);
|
memset(ADU, 0, ADUSIZE);
|
||||||
if (a->state != AsconReadDone) {
|
return 0;
|
||||||
if (a->timeout > 0) {
|
|
||||||
if (DoubleTime() - a->start > a->timeout) {
|
|
||||||
AsconError(a, "read timeout", 0);
|
|
||||||
a->state = AsconTimeout;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TCPMBUtil(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) {
|
int TCPMBUtil(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) {
|
||||||
|
|||||||
Reference in New Issue
Block a user