Skip to content

Commit

Permalink
- CS104: fixed timeout T2 problem (S message was sent before timeout …
Browse files Browse the repository at this point in the history
…elapsed)
  • Loading branch information
mzillgith committed Apr 14, 2018
1 parent e27b365 commit 9fadedc
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 10 deletions.
16 changes: 11 additions & 5 deletions lib60870-C/src/iec60870/cs104/cs104_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,10 @@ struct sCS104_Connection {
int receiveCount;
int sendCount;

bool firstIMessageReceived;

int unconfirmedReceivedIMessages;

/* timeout T2 handling */
bool timeoutT2Trigger;
uint64_t lastConfirmationTime;

uint64_t nextT3Timeout;
Expand Down Expand Up @@ -173,6 +174,9 @@ sendIMessage(CS104_Connection self, Frame frame)

self->sendCount = (self->sendCount + 1) % 32768;

self->unconfirmedReceivedIMessages = false;
self->timeoutT2Trigger = false;

return self->sendCount;
}

Expand Down Expand Up @@ -258,7 +262,7 @@ resetConnection(CS104_Connection self)

self->unconfirmedReceivedIMessages = 0;
self->lastConfirmationTime = 0xffffffffffffffff;
self->firstIMessageReceived = false;
self->timeoutT2Trigger = false;

self->oldestSentASDU = -1;
self->newestSentASDU = -1;
Expand Down Expand Up @@ -500,8 +504,8 @@ checkMessage(CS104_Connection self, uint8_t* buffer, int msgSize)
{
if ((buffer[2] & 1) == 0) { /* I format frame */

if (self->firstIMessageReceived == false) {
self->firstIMessageReceived = true;
if (self->timeoutT2Trigger == false) {
self->timeoutT2Trigger = true;
self->lastConfirmationTime = Hal_getTimeInMs(); /* start timeout T2 */
}

Expand Down Expand Up @@ -619,6 +623,7 @@ handleTimeouts(CS104_Connection self)

self->lastConfirmationTime = currentTime;
self->unconfirmedReceivedIMessages = 0;
self->timeoutT2Trigger = false;

sendSMessage(self); /* send confirmation message */
}
Expand Down Expand Up @@ -717,6 +722,7 @@ handleConnection(void* parameter)
if (self->unconfirmedReceivedIMessages >= self->parameters.w) {
self->lastConfirmationTime = Hal_getTimeInMs();
self->unconfirmedReceivedIMessages = 0;
self->timeoutT2Trigger = false;
sendSMessage(self);
}
}
Expand Down
15 changes: 10 additions & 5 deletions lib60870-C/src/iec60870/cs104/cs104_slave.c
Original file line number Diff line number Diff line change
Expand Up @@ -951,7 +951,10 @@ struct sMasterConnection {
int receiveCount; /* received messages - sequence counter */

int unconfirmedReceivedIMessages; /* number of unconfirmed messages received */

/* timeout T2 handling */
uint64_t lastConfirmationTime; /* timestamp when the last confirmation message (for I messages) was sent */
bool timeoutT2Triggered;

uint64_t nextT3Timeout;
int outstandingTestFRConMessages;
Expand All @@ -966,8 +969,6 @@ struct sMasterConnection {

MessageQueue lowPrioQueue;
HighPriorityASDUQueue highPrioQueue;

bool firstIMessageReceived;
};


Expand Down Expand Up @@ -1090,6 +1091,7 @@ sendIMessage(MasterConnection self, uint8_t* buffer, int msgSize)
DEBUG_PRINT("SEND I (size = %i) N(S) = %i N(R) = %i\n", msgSize, self->sendCount, self->receiveCount);
self->sendCount = (self->sendCount + 1) % 32768;
self->unconfirmedReceivedIMessages = 0;
self->timeoutT2Triggered = false;
}
else
self->isRunning = false;
Expand Down Expand Up @@ -1487,8 +1489,8 @@ handleMessage(MasterConnection self, uint8_t* buffer, int msgSize)
return false;
}

if (self->firstIMessageReceived == false) {
self->firstIMessageReceived = true;
if (self->timeoutT2Triggered == false) {
self->timeoutT2Triggered = true;
self->lastConfirmationTime = currentTime; /* start timeout T2 */
}

Expand Down Expand Up @@ -1739,6 +1741,7 @@ handleTimeouts(MasterConnection self)
if ((currentTime - self->lastConfirmationTime) >= (uint64_t) (self->slave->conParameters.t2 * 1000)) {
self->lastConfirmationTime = currentTime;
self->unconfirmedReceivedIMessages = 0;
self->timeoutT2Triggered = false;
sendSMessage(self);
}
}
Expand Down Expand Up @@ -1837,6 +1840,8 @@ connectionHandlingThread(void* parameter)

self->unconfirmedReceivedIMessages = 0;

self->timeoutT2Triggered = false;

sendSMessage(self);
}
}
Expand Down Expand Up @@ -1927,7 +1932,7 @@ MasterConnection_create(CS104_Slave slave, Socket socket, MessageQueue lowPrioQu
self->unconfirmedReceivedIMessages = 0;
self->lastConfirmationTime = UINT64_MAX;

self->firstIMessageReceived = false;
self->timeoutT2Triggered = false;

self->maxSentASDUs = slave->conParameters.k;
self->oldestSentASDU = -1;
Expand Down
2 changes: 2 additions & 0 deletions user_guide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,8 @@ For *select before operate* the command has to be sent with the _selectCommand_

If the command has been successful the outstation will answer with an ACT_CON response message with the _negative flag_ not set. In case the outstation cannot execute the command it will also answer with an ACT_CON response but with the _negative flag_ set. You can check if this flag is set with the _CS101_ASDU_isNegative_ function used with the received _CS101_ASDU_ instance.

For a CS 104 master a command can be sent the same way by using the _CS104_Master_sendProcessCommandEx_ function.


== Slave (server) side programming

Expand Down

0 comments on commit 9fadedc

Please sign in to comment.