Skip to content

Commit

Permalink
- CS101 unbalanced master: always send request status of link before …
Browse files Browse the repository at this point in the history
…reset link; added timeout to delay link status request
  • Loading branch information
mzillgith committed Dec 29, 2022
1 parent 0c9a8f1 commit ee832dd
Show file tree
Hide file tree
Showing 10 changed files with 99 additions and 33 deletions.
4 changes: 2 additions & 2 deletions lib60870-C/examples/cs101_master_balanced/master_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ main(int argc, char** argv)

CS101_Master master = CS101_Master_create(port, NULL, NULL, IEC60870_LINK_LAYER_BALANCED);


CS101_Master_setOwnAddress(master, 2);

/* Set the address of the slave (optional for balanced master */
Expand All @@ -132,11 +131,12 @@ main(int argc, char** argv)
/* modify some of the default parameters */
LinkLayerParameters llParams = CS101_Master_getLinkLayerParameters(master);
llParams->useSingleCharACK = false;
llParams->addressLength = 1;

/* set handler for link layer state changes */
CS101_Master_setLinkLayerStateChanged(master, linkLayerStateChanged, NULL);

/* uncomment to log messages */
/* log messages */
CS101_Master_setRawMessageHandler(master, rawMessageHandler, NULL);

SerialPort_open(port);
Expand Down
20 changes: 20 additions & 0 deletions lib60870-C/examples/cs101_master_unbalanced/master_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@ sigint_handler(int signalId)
running = false;
}

/* Callback handler to log sent or received messages (optional) */
static void
rawMessageHandler (void* parameter, uint8_t* msg, int msgSize, bool sent)
{
if (sent)
printf("SEND: ");
else
printf("RCVD: ");

int i;
for (i = 0; i < msgSize; i++) {
printf("%02x ", msg[i]);
}

printf("\n");
}

static bool
asduReceivedHandler (void* parameter, int address, CS101_ASDU asdu)
{
Expand Down Expand Up @@ -154,6 +171,9 @@ main(int argc, char** argv)
/* set callback handler for link layer state changes */
CS101_Master_setLinkLayerStateChanged(master, linkLayerStateChanged, NULL);

/* log messages */
CS101_Master_setRawMessageHandler(master, rawMessageHandler, NULL);

CS101_Master_addSlave(master, 1);
CS101_Master_addSlave(master, 2);

Expand Down
9 changes: 3 additions & 6 deletions lib60870-C/examples/cs101_slave/slave_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ main(int argc, char** argv)
SerialPort port = SerialPort_create(serialPort, 9600, 8, 'E', 1);

/* create a new slave/server instance with default link layer and application layer parameters */
// CS101_Slave slave = CS101_Slave_create(port, NULL, NULL, IEC60870_LINK_LAYER_BALANCED);
//CS101_Slave slave = CS101_Slave_create(port, NULL, NULL, IEC60870_LINK_LAYER_BALANCED);
CS101_Slave slave = CS101_Slave_create(port, NULL, NULL, IEC60870_LINK_LAYER_UNBALANCED);

CS101_Slave_setLinkLayerAddress(slave, 1);
Expand All @@ -239,6 +239,7 @@ main(int argc, char** argv)

LinkLayerParameters llParameters = CS101_Slave_getLinkLayerParameters(slave);
llParameters->timeoutForAck = 500;
llParameters->addressLength = 1;

/* set the callback handler for the clock synchronization command */
CS101_Slave_setClockSyncHandler(slave, clockSyncHandler, NULL);
Expand All @@ -258,7 +259,7 @@ main(int argc, char** argv)
/* set handler for link layer state changes */
CS101_Slave_setLinkLayerStateChanged(slave, linkLayerStateChanged, NULL);

/* uncomment to log messages */
/* log messages */
CS101_Slave_setRawMessageHandler(slave, rawMessageHandler, NULL);

int16_t scaledValue = 0;
Expand Down Expand Up @@ -303,7 +304,3 @@ main(int argc, char** argv)
SerialPort_close(port);
SerialPort_destroy(port);
}




5 changes: 3 additions & 2 deletions lib60870-C/src/iec60870/cs101/cs101_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ CS101_Master_createEx(SerialPort serialPort, LinkLayerParameters llParameters, C
self->linkLayerParameters.addressLength = 1;
self->linkLayerParameters.timeoutForAck = 200;
self->linkLayerParameters.timeoutRepeat = 1000;
self->linkLayerParameters.timeoutLinkState = 5000;
self->linkLayerParameters.useSingleCharACK = true;
}

Expand Down Expand Up @@ -232,11 +233,11 @@ void
CS101_Master_run(CS101_Master self)
{
if (self->unbalancedLinkLayer) {

LinkLayerPrimaryUnbalanced_run(self->unbalancedLinkLayer);
}
else
else {
LinkLayerBalanced_run(self->balancedLinkLayer);
}
}

#if (CONFIG_USE_THREADS == 1)
Expand Down
79 changes: 65 additions & 14 deletions lib60870-C/src/iec60870/link_layer/link_layer.c
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,7 @@ LinkLayerSecondaryBalanced_handleMessage(LinkLayerSecondaryBalanced self, uint8_

case LL_FC_09_REQUEST_LINK_STATUS:

DEBUG_PRINT ("SLL - RECV FC 09 - REQUEST LINK STATUS");
DEBUG_PRINT ("SLL - RECV FC 09 - REQUEST LINK STATUS\n");

DEBUG_PRINT ("SLL - SEND FC 11 - STATUS OF LINK\n");

Expand Down Expand Up @@ -875,7 +875,8 @@ typedef enum {
PLL_LINK_LAYERS_AVAILABLE,
PLL_EXECUTE_SERVICE_SEND_CONFIRM,
PLL_EXECUTE_SERVICE_REQUEST_RESPOND,
PLL_SECONDARY_LINK_LAYER_BUSY /* Only required in balanced link layer */
PLL_SECONDARY_LINK_LAYER_BUSY, /* Only required in balanced link layer */
PLL_TIMEOUT /* only required in unbalanced link layer */
} PrimaryLinkLayerState;

struct sLinkLayerPrimaryBalanced {
Expand Down Expand Up @@ -1146,6 +1147,12 @@ LinkLayerPrimaryBalanced_runStateMachine(LinkLayerPrimaryBalanced self)
case PLL_EXECUTE_RESET_REMOTE_LINK:

if (self->waitingForResponse) {

if (self->lastSendTime > currentTime) {
/* last sent time not plausible! */
self->lastSendTime = currentTime;
}

if (currentTime > (self->lastSendTime + self->linkLayer->linkLayerParameters->timeoutForAck)) {
self->waitingForResponse = false;
newState = PLL_IDLE;
Expand Down Expand Up @@ -1208,6 +1215,11 @@ LinkLayerPrimaryBalanced_runStateMachine(LinkLayerPrimaryBalanced self)

case PLL_EXECUTE_SERVICE_SEND_CONFIRM:

if (self->lastSendTime > currentTime) {
/* last sent time not plausible! */
self->lastSendTime = currentTime;
}

if (currentTime > (self->lastSendTime + self->linkLayer->linkLayerParameters->timeoutForAck)) {

if (currentTime > (self->originalSendTime + self->linkLayer->linkLayerParameters->timeoutRepeat)) {
Expand Down Expand Up @@ -1713,20 +1725,37 @@ llsc_isMessageWaitingToSend(LinkLayerSlaveConnection self)
static void
LinkLayerSlaveConnection_runStateMachine(LinkLayerSlaveConnection self)
{
/* TODO make timeouts dealing with time adjustments (time moves to past) */
uint64_t currentTime = Hal_getTimeInMs();

PrimaryLinkLayerState primaryState = self->primaryState;
PrimaryLinkLayerState newState = primaryState;

switch (primaryState) {

case PLL_TIMEOUT:

if (self->lastSendTime > currentTime) {
/* last sent time not plausible! */
self->lastSendTime = currentTime;
}

if (currentTime > (self->lastSendTime + self->primaryLink->linkLayer->linkLayerParameters->timeoutLinkState)) {
newState = PLL_IDLE;
}

break;

case PLL_IDLE:

self->waitingForResponse = false;
self->originalSendTime = 0;
self->lastSendTime = 0;
self->sendLinkLayerTestFunction = false;

DEBUG_PRINT ("[SLAVE %i] PLL - SEND FC 09 - REQUEST LINK STATUS\n", self->address);

SendFixedFrame(self->primaryLink->linkLayer, LL_FC_09_REQUEST_LINK_STATUS, self->address, true, false, false, false);

self->lastSendTime = currentTime;
self->waitingForResponse = true;
newState = PLL_EXECUTE_REQUEST_STATUS_OF_LINK;

break;
Expand All @@ -1735,13 +1764,15 @@ LinkLayerSlaveConnection_runStateMachine(LinkLayerSlaveConnection self)

if (self->waitingForResponse) {

if (currentTime > (self->lastSendTime + self->primaryLink->linkLayer->linkLayerParameters->timeoutForAck)) {

DEBUG_PRINT ("[SLAVE %i] PLL - SEND FC 09 - REQUEST LINK STATUS\n", self->address);

SendFixedFrame(self->primaryLink->linkLayer, LL_FC_09_REQUEST_LINK_STATUS, self->address, true, false, false, false);
if (self->lastSendTime > currentTime) {
/* last sent time not plausible! */
self->lastSendTime = currentTime;
}

if (currentTime > (self->lastSendTime + self->primaryLink->linkLayer->linkLayerParameters->timeoutForAck)) {
self->waitingForResponse = false;
self->lastSendTime = currentTime;
newState = PLL_TIMEOUT;
}

}
Expand All @@ -1761,9 +1792,16 @@ LinkLayerSlaveConnection_runStateMachine(LinkLayerSlaveConnection self)
case PLL_EXECUTE_RESET_REMOTE_LINK:

if (self->waitingForResponse) {

if (self->lastSendTime > currentTime) {
/* last sent time not plausible! */
self->lastSendTime = currentTime;
}

if (currentTime > (self->lastSendTime + self->primaryLink->linkLayer->linkLayerParameters->timeoutForAck)) {
self->waitingForResponse = false;
newState = PLL_IDLE;
self->lastSendTime = currentTime;
newState = PLL_TIMEOUT;

llsc_setState(self, LL_STATE_ERROR);
}
Expand Down Expand Up @@ -1831,11 +1869,19 @@ LinkLayerSlaveConnection_runStateMachine(LinkLayerSlaveConnection self)

case PLL_EXECUTE_SERVICE_SEND_CONFIRM:

if (self->lastSendTime > currentTime) {
/* last sent time not plausible! */
self->lastSendTime = currentTime;
}

if (currentTime > (self->lastSendTime + self->primaryLink->linkLayer->linkLayerParameters->timeoutForAck)) {

if (currentTime > (self->originalSendTime + self->primaryLink->linkLayer->linkLayerParameters->timeoutRepeat)) {
DEBUG_PRINT ("[SLAVE %i] TIMEOUT: ASDU not confirmed after repeated transmission\n", self->address);
newState = PLL_IDLE;

self->waitingForResponse = false;
self->lastSendTime = currentTime;
newState = PLL_TIMEOUT;

llsc_setState(self, LL_STATE_ERROR);
}
Expand Down Expand Up @@ -1866,6 +1912,11 @@ LinkLayerSlaveConnection_runStateMachine(LinkLayerSlaveConnection self)

case PLL_EXECUTE_SERVICE_REQUEST_RESPOND:

if (self->lastSendTime > currentTime) {
/* last sent time not plausible! */
self->lastSendTime = currentTime;
}

if (currentTime > (self->lastSendTime + self->primaryLink->linkLayer->linkLayerParameters->timeoutForAck)) {

if (currentTime > (self->originalSendTime + self->primaryLink->linkLayer->linkLayerParameters->timeoutRepeat)) {
Expand Down Expand Up @@ -1941,7 +1992,6 @@ LinkLayerPrimaryUnbalanced_addSlaveConnection(LinkLayerPrimaryUnbalanced self, i

LinkedList_add(self->slaveConnections, newSlave);
}

}

void
Expand Down Expand Up @@ -2100,7 +2150,8 @@ LinkLayerPrimaryUnbalanced_runStateMachine(LinkLayerPrimaryUnbalanced self)
self->currentSlaveIndex = (self->currentSlaveIndex + 1) % LinkedList_size(self->slaveConnections);
}

LinkLayerSlaveConnection_runStateMachine(self->currentSlave);
if (self->currentSlave)
LinkLayerSlaveConnection_runStateMachine(self->currentSlave);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* serial_transceiver_ft_1_2.c
*
* Copyright 2017 MZ Automation GmbH
* Copyright 2017-2022 Michael Zillgith
*
* This file is part of lib60870-C
*
Expand Down Expand Up @@ -194,7 +194,3 @@ SerialTransceiverFT12_readNextMessage(SerialTransceiverFT12 self, uint8_t* buffe

return;
}




2 changes: 1 addition & 1 deletion lib60870-C/src/inc/api/cs101_master.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* cs101_master.h
*
* Copyright 2017 MZ Automation GmbH
* Copyright 2017-2022 Michael Zillgith
*
* This file is part of lib60870-C
*
Expand Down
2 changes: 1 addition & 1 deletion lib60870-C/src/inc/api/cs101_slave.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* cs101_slave.h
*
* Copyright 2017 MZ Automation GmbH
* Copyright 2017-2022 Michael Zillgith
*
* This file is part of lib60870-C
*
Expand Down
2 changes: 1 addition & 1 deletion lib60870-C/src/inc/api/iec60870_master.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016 MZ Automation GmbH
* Copyright 2016-2022 Michael Zillgith
*
* This file is part of lib60870-C
*
Expand Down
3 changes: 2 additions & 1 deletion lib60870-C/src/inc/api/link_layer_parameters.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* link_layer_parameters.h
*
* Copyright 2017 MZ Automation GmbH
* Copyright 2017-2022 Michael Zillgith
*
* This file is part of lib60870-C
*
Expand Down Expand Up @@ -44,6 +44,7 @@ struct sLinkLayerParameters {
int timeoutForAck; /** timeout for link layer ACK in ms */
int timeoutRepeat; /** timeout for repeated message transmission when no ACK received in ms */
bool useSingleCharACK; /** use single char ACK for ACK (FC=0) or RESP_NO_USER_DATA (FC=9) */
int timeoutLinkState; /** interval to repeat request status of link (FC=9) after response timeout */
};

#ifdef __cplusplus
Expand Down

0 comments on commit ee832dd

Please sign in to comment.