1
0
mirror of https://github.com/stargieg/bacnet-stack synced 2025-10-26 23:35:52 +08:00

[r3133] Fixed MS/TP ANSWER_DATA_REQUEST state in some of the ports to be compliant to the standard by emitting Reply-Postponed rather than nothing when the data request times out.

This commit is contained in:
Steve Karg
2017-05-02 22:17:39 +02:00
committed by Patrick Grimm
parent 28a17e0b34
commit d33bec7472
2 changed files with 94 additions and 98 deletions

View File

@@ -666,22 +666,22 @@ static bool MSTP_Master_Node_FSM(
/* The number of frames sent by this node during a single token hold. */
/* When this counter reaches the value Nmax_info_frames, the node must */
/* pass the token. */
static uint8_t FrameCount;
static uint8_t FrameCount = 0;
/* "Next Station," the MAC address of the node to which This Station
passes the token. If the Next_Station is unknown, Next_Station shall
be equal to This_Station. */
static uint8_t Next_Station;
static uint8_t Next_Station = 0;
/* "Poll Station," the MAC address of the node to which This Station last */
/* sent a Poll For Master. This is used during token maintenance. */
static uint8_t Poll_Station;
static uint8_t Poll_Station = 0;
/* A counter of transmission retries used for Token and Poll For Master */
/* transmission. */
static unsigned RetryCount;
static unsigned RetryCount = 0;
/* The number of tokens received by this node. When this counter reaches */
/* the value Npoll, the node polls the address range between TS and NS */
/* for additional master nodes. TokenCount is set to zero at the end of */
/* the polling process. */
static unsigned TokenCount;
static unsigned TokenCount = 0;
/* next-x-station calculations */
uint8_t next_poll_station = 0;
uint8_t next_this_station = 0;
@@ -689,10 +689,11 @@ static bool MSTP_Master_Node_FSM(
/* timeout values */
uint16_t my_timeout = 10, ns_timeout = 0;
bool matched = false;
bool timeout = false;
/* transition immediately to the next state */
bool transition_now = false;
/* packet from the PDU Queue */
struct mstp_pdu_packet *pkt;
struct mstp_pdu_packet *pkt = NULL;
/* some calculations that several states need */
next_poll_station = (Poll_Station + 1) % (Nmax_master + 1);
@@ -1120,15 +1121,12 @@ static bool MSTP_Master_Node_FSM(
MSTP_Flag.ReceivedInvalidFrame = false;
}
break;
case MSTP_MASTER_STATE_ANSWER_DATA_REQUEST:
/* The ANSWER_DATA_REQUEST state is entered when a */
/* BACnet Data Expecting Reply, a Test_Request, or */
/* a proprietary frame that expects a reply is received. */
case MSTP_MASTER_STATE_ANSWER_DATA_REQUEST:
if (rs485_silence_time_elapsed(Treply_delay)) {
Master_State = MSTP_MASTER_STATE_IDLE;
/* clear our flag we were holding for comparison */
MSTP_Flag.ReceivedValidFrame = false;
} else {
timeout = rs485_silence_time_elapsed(Treply_delay);
if (!timeout) {
pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&PDU_Queue);
if (pkt != NULL) {
matched =
@@ -1138,45 +1136,45 @@ static bool MSTP_Master_Node_FSM(
} else {
matched = false;
}
if (matched) {
/* Reply */
/* If a reply is available from the higher layers */
/* within Treply_delay after the reception of the */
/* final octet of the requesting frame */
/* (the mechanism used to determine this is a local matter), */
/* then call MSTP_Send_Frame to transmit the reply frame */
/* and enter the IDLE state to wait for the next frame. */
uint8_t frame_type;
if (pkt->data_expecting_reply) {
frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY;
} else {
frame_type =
FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
}
MSTP_Send_Frame(frame_type, pkt->destination_mac,
This_Station, (uint8_t *) & pkt->buffer[0],
pkt->length);
Master_State = MSTP_MASTER_STATE_IDLE;
/* clear our flag we were holding for comparison */
MSTP_Flag.ReceivedValidFrame = false;
/* clear the queue */
(void) Ringbuf_Pop(&PDU_Queue, NULL);
} else if (pkt != NULL) {
/* DeferredReply */
/* If no reply will be available from the higher layers */
/* within Treply_delay after the reception of the */
/* final octet of the requesting frame (the mechanism */
/* used to determine this is a local matter), */
/* then an immediate reply is not possible. */
/* Any reply shall wait until this node receives the token. */
/* Call MSTP_Send_Frame to transmit a Reply Postponed frame, */
/* and enter the IDLE state. */
MSTP_Send_Frame(FRAME_TYPE_REPLY_POSTPONED, SourceAddress,
This_Station, NULL, 0);
Master_State = MSTP_MASTER_STATE_IDLE;
/* clear our flag we were holding for comparison */
MSTP_Flag.ReceivedValidFrame = false;
}
if (matched) {
/* Reply */
/* If a reply is available from the higher layers */
/* within Treply_delay after the reception of the */
/* final octet of the requesting frame */
/* (the mechanism used to determine this is a local matter), */
/* then call MSTP_Send_Frame to transmit the reply frame */
/* and enter the IDLE state to wait for the next frame. */
uint8_t frame_type;
if (pkt->data_expecting_reply) {
frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY;
} else {
frame_type =
FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
}
MSTP_Send_Frame(frame_type, pkt->destination_mac,
This_Station, (uint8_t *) & pkt->buffer[0],
pkt->length);
Master_State = MSTP_MASTER_STATE_IDLE;
/* clear our flag we were holding for comparison */
MSTP_Flag.ReceivedValidFrame = false;
/* clear the queue */
(void) Ringbuf_Pop(&PDU_Queue, NULL);
} else if ((pkt != NULL) || timeout) {
/* DeferredReply */
/* If no reply will be available from the higher layers */
/* within Treply_delay after the reception of the */
/* final octet of the requesting frame (the mechanism */
/* used to determine this is a local matter), */
/* then an immediate reply is not possible. */
/* Any reply shall wait until this node receives the token. */
/* Call MSTP_Send_Frame to transmit a Reply Postponed frame, */
/* and enter the IDLE state. */
MSTP_Send_Frame(FRAME_TYPE_REPLY_POSTPONED, SourceAddress,
This_Station, NULL, 0);
Master_State = MSTP_MASTER_STATE_IDLE;
/* clear our flag we were holding for comparison */
MSTP_Flag.ReceivedValidFrame = false;
}
break;
default:

View File

@@ -725,22 +725,22 @@ static bool MSTP_Master_Node_FSM(void)
/* The number of frames sent by this node during a single token hold. */
/* When this counter reaches the value Nmax_info_frames, the node must */
/* pass the token. */
static uint8_t FrameCount;
static uint8_t FrameCount = 0;
/* "Next Station," the MAC address of the node to which This Station
passes the token. If the Next_Station is unknown, Next_Station shall
be equal to This_Station. */
static uint8_t Next_Station;
static uint8_t Next_Station = 0;
/* "Poll Station," the MAC address of the node to which This Station last */
/* sent a Poll For Master. This is used during token maintenance. */
static uint8_t Poll_Station;
/* A counter of transmission retries used for Token and Poll For Master */
/* transmission. */
static unsigned RetryCount;
static unsigned RetryCount = 0;
/* The number of tokens received by this node. When this counter reaches */
/* the value Npoll, the node polls the address range between TS and NS */
/* for additional master nodes. TokenCount is set to zero at the end of */
/* the polling process. */
static unsigned TokenCount;
static unsigned TokenCount = 0;
/* next-x-station calculations */
uint8_t next_poll_station = 0;
uint8_t next_this_station = 0;
@@ -748,10 +748,11 @@ static bool MSTP_Master_Node_FSM(void)
/* timeout values */
uint16_t my_timeout = 10, ns_timeout = 0;
bool matched = false;
bool timeout = false;
/* transition immediately to the next state */
bool transition_now = false;
/* packet from the PDU Queue */
struct mstp_pdu_packet *pkt;
struct mstp_pdu_packet *pkt = NULL;
/* some calculations that several states need */
next_poll_station = (Poll_Station + 1) % (Nmax_master + 1);
@@ -1183,11 +1184,8 @@ static bool MSTP_Master_Node_FSM(void)
/* BACnet Data Expecting Reply, a Test_Request, or */
/* a proprietary frame that expects a reply is received. */
case MSTP_MASTER_STATE_ANSWER_DATA_REQUEST:
if (rs485_silence_elapsed(Treply_delay)) {
Master_State = MSTP_MASTER_STATE_IDLE;
/* clear our flag we were holding for comparison */
MSTP_Flag.ReceivedValidFrame = false;
} else {
timeout = rs485_silence_elapsed(Treply_delay);
if (!timeout) {
pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&PDU_Queue);
if (pkt != NULL) {
matched =
@@ -1197,45 +1195,45 @@ static bool MSTP_Master_Node_FSM(void)
} else {
matched = false;
}
if (matched) {
/* Reply */
/* If a reply is available from the higher layers */
/* within Treply_delay after the reception of the */
/* final octet of the requesting frame */
/* (the mechanism used to determine this is a local matter), */
/* then call MSTP_Send_Frame to transmit the reply frame */
/* and enter the IDLE state to wait for the next frame. */
uint8_t frame_type;
if (pkt->data_expecting_reply) {
frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY;
} else {
frame_type =
FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
}
MSTP_Send_Frame(frame_type, pkt->destination_mac,
This_Station, (uint8_t *) & pkt->buffer[0],
pkt->length);
Master_State = MSTP_MASTER_STATE_IDLE;
/* clear our flag we were holding for comparison */
MSTP_Flag.ReceivedValidFrame = false;
/* clear the queue */
(void) Ringbuf_Pop(&PDU_Queue, NULL);
} else if (pkt != NULL) {
/* DeferredReply */
/* If no reply will be available from the higher layers */
/* within Treply_delay after the reception of the */
/* final octet of the requesting frame (the mechanism */
/* used to determine this is a local matter), */
/* then an immediate reply is not possible. */
/* Any reply shall wait until this node receives the token. */
/* Call MSTP_Send_Frame to transmit a Reply Postponed frame, */
/* and enter the IDLE state. */
MSTP_Send_Frame(FRAME_TYPE_REPLY_POSTPONED, SourceAddress,
This_Station, NULL, 0);
Master_State = MSTP_MASTER_STATE_IDLE;
/* clear our flag we were holding for comparison */
MSTP_Flag.ReceivedValidFrame = false;
}
if (matched) {
/* Reply */
/* If a reply is available from the higher layers */
/* within Treply_delay after the reception of the */
/* final octet of the requesting frame */
/* (the mechanism used to determine this is a local matter), */
/* then call MSTP_Send_Frame to transmit the reply frame */
/* and enter the IDLE state to wait for the next frame. */
uint8_t frame_type;
if (pkt->data_expecting_reply) {
frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY;
} else {
frame_type =
FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
}
MSTP_Send_Frame(frame_type, pkt->destination_mac,
This_Station, (uint8_t *) & pkt->buffer[0],
pkt->length);
Master_State = MSTP_MASTER_STATE_IDLE;
/* clear our flag we were holding for comparison */
MSTP_Flag.ReceivedValidFrame = false;
/* clear the queue */
(void) Ringbuf_Pop(&PDU_Queue, NULL);
} else if ((pkt != NULL) || timeout) {
/* DeferredReply */
/* If no reply will be available from the higher layers */
/* within Treply_delay after the reception of the */
/* final octet of the requesting frame (the mechanism */
/* used to determine this is a local matter), */
/* then an immediate reply is not possible. */
/* Any reply shall wait until this node receives the token. */
/* Call MSTP_Send_Frame to transmit a Reply Postponed frame, */
/* and enter the IDLE state. */
MSTP_Send_Frame(FRAME_TYPE_REPLY_POSTPONED, SourceAddress,
This_Station, NULL, 0);
Master_State = MSTP_MASTER_STATE_IDLE;
/* clear our flag we were holding for comparison */
MSTP_Flag.ReceivedValidFrame = false;
}
break;
default: