⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dlmstp.c

📁 Bacnet protocol stack for linux
💻 C
📖 第 1 页 / 共 4 页
字号:
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;
    /* "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;
    /* "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;
    /* 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;
    /* next-x-station calculations */
    uint8_t next_poll_station = 0;
    uint8_t next_this_station = 0;
    uint8_t next_next_station = 0;
    /* timeout values */
    uint16_t my_timeout = 10, ns_timeout = 0;
    bool matched;
    /* transition immediately to the next state */
    bool transition_now = false;

    /* some calculations that several states need */
    next_poll_station = (Poll_Station + 1) % (Nmax_master + 1);
    next_this_station = (This_Station + 1) % (Nmax_master + 1);
    next_next_station = (Next_Station + 1) % (Nmax_master + 1);
    switch (Master_State) {
        case MSTP_MASTER_STATE_INITIALIZE:
            /* DoneInitializing */
            /* indicate that the next station is unknown */
            Next_Station = This_Station;
            Poll_Station = This_Station;
            /* cause a Poll For Master to be sent when this node first */
            /* receives the token */
            TokenCount = Npoll;
            MSTP_Flag.SoleMaster = false;
            Master_State = MSTP_MASTER_STATE_IDLE;
            transition_now = true;
            break;
        case MSTP_MASTER_STATE_IDLE:
            /* In the IDLE state, the node waits for a frame. */
            if (Timer_Silence() >= Tno_token) {
                /* LostToken */
                /* assume that the token has been lost */
                EventCount = 0; /* Addendum 135-2004d-8 */
                Master_State = MSTP_MASTER_STATE_NO_TOKEN;
                transition_now = true;
            } else if (MSTP_Flag.ReceivedInvalidFrame == true) {
                /* ReceivedInvalidFrame */
                /* invalid frame was received */
                MSTP_Flag.ReceivedInvalidFrame = false;
                /* wait for the next frame - remain in IDLE */
            } else if (MSTP_Flag.ReceivedValidFrame == true) {
                switch (FrameType) {
                    case FRAME_TYPE_TOKEN:
                        /* ReceivedToken */
                        /* tokens can't be broadcast */
                        if (DestinationAddress == MSTP_BROADCAST_ADDRESS)
                            break;
                        MSTP_Flag.ReceivedValidFrame = false;
                        FrameCount = 0;
                        MSTP_Flag.SoleMaster = false;
                        Master_State = MSTP_MASTER_STATE_USE_TOKEN;
                        transition_now = true;
                        break;
                    case FRAME_TYPE_POLL_FOR_MASTER:
                        /* ReceivedPFM */
                        MSTP_Send_Frame(FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER,
                            SourceAddress, This_Station, NULL, 0);
                        break;
                    case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY:
                        /* indicate successful reception to the higher layers */
                        MSTP_Flag.ReceivePacketPending = true;
                        break;
                    case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY:
                        /* indicate successful reception to higher layers */
                        MSTP_Flag.ReceivePacketPending = true;
                        /* broadcast DER just remains IDLE */
                        if (DestinationAddress != MSTP_BROADCAST_ADDRESS) {
                            Master_State =
                                MSTP_MASTER_STATE_ANSWER_DATA_REQUEST;
                        }
                        break;
                    case FRAME_TYPE_TEST_REQUEST:
                        MSTP_Send_Frame(FRAME_TYPE_TEST_RESPONSE,
                            SourceAddress, This_Station, &InputBuffer[0],
                            DataLength);
                        break;
                    case FRAME_TYPE_TEST_RESPONSE:
                    default:
                        break;
                }
                /* For DATA_EXPECTING_REPLY, we will keep the Rx Frame for 
                   reference, and the flag will be cleared in the next state */
                if (Master_State != MSTP_MASTER_STATE_ANSWER_DATA_REQUEST) {
                    MSTP_Flag.ReceivedValidFrame = false;
                }
            }
            break;
            /* In the USE_TOKEN state, the node is allowed to send one or  */
            /* more data frames. These may be BACnet Data frames or */
            /* proprietary frames. */
        case MSTP_MASTER_STATE_USE_TOKEN:
            /* Note: We could wait for up to Tusage_delay */
            if (!MSTP_Flag.TransmitPacketPending) {
                /* NothingToSend */
                FrameCount = Nmax_info_frames;
                Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
                transition_now = true;
            } else {
                uint8_t frame_type;
                if (MSTP_Flag.TransmitPacketDER) {
                    frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY;
                } else {
                    frame_type = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
                }
                MSTP_Send_Frame(frame_type, TransmitPacketDest, This_Station,
                    (uint8_t *) & TransmitPacket[0], TransmitPacketLen);
                MSTP_Flag.TransmitPacketPending = false;
                FrameCount++;
                switch (frame_type) {
                    case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY:
                        /* SendAndWait */
                        if (TransmitPacketDest == MSTP_BROADCAST_ADDRESS)
                            Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
                        else
                            Master_State = MSTP_MASTER_STATE_WAIT_FOR_REPLY;
                        break;
                    case FRAME_TYPE_TEST_REQUEST:
                        Master_State = MSTP_MASTER_STATE_WAIT_FOR_REPLY;
                        break;
                    case FRAME_TYPE_TEST_RESPONSE:
                    case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY:
                    default:
                        /* SendNoWait */
                        Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
                        break;
                }
            }
            break;
        case MSTP_MASTER_STATE_WAIT_FOR_REPLY:
            /* In the WAIT_FOR_REPLY state, the node waits for  */
            /* a reply from another node. */
            if (Timer_Silence() >= Treply_timeout) {
                /* ReplyTimeout */
                /* assume that the request has failed */
                FrameCount = Nmax_info_frames;
                Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
                /* Any retry of the data frame shall await the next entry */
                /* to the USE_TOKEN state. */
                /* (Because of the length of the timeout,  */
                /* this transition will cause the token to be */
                /* passed regardless */
                /* of the initial value of FrameCount.) */
                transition_now = true;
            } else {
                if (MSTP_Flag.ReceivedInvalidFrame == true) {
                    /* InvalidFrame */
                    /* error in frame reception */
                    MSTP_Flag.ReceivedInvalidFrame = false;
                    Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
                    transition_now = true;
                } else if (MSTP_Flag.ReceivedValidFrame == true) {
                    if (DestinationAddress == This_Station) {
                        /* What did we receive? */
                        switch (FrameType) {
                            case FRAME_TYPE_REPLY_POSTPONED:
                                /* ReceivedReplyPostponed */
                                Master_State =
                                    MSTP_MASTER_STATE_DONE_WITH_TOKEN;
                                break;
                            case FRAME_TYPE_TEST_RESPONSE:
                                Master_State = MSTP_MASTER_STATE_IDLE;
                                break;
                            case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY:
                                /* ReceivedReply */
                                /* or a proprietary type that indicates
                                   a reply */
                                /* indicate successful reception to 
                                   the higher layers */
                                MSTP_Flag.ReceivePacketPending = true;
                                Master_State =
                                    MSTP_MASTER_STATE_DONE_WITH_TOKEN;
                                break;
                            default:
                                /* if proprietary frame was expected, you might
                                   need to transition to DONE WITH TOKEN */
                                Master_State = MSTP_MASTER_STATE_IDLE;
                                break;
                        }
                    } else {
                        /* ReceivedUnexpectedFrame */
                        /* an unexpected frame was received */
                        /* This may indicate the presence of multiple tokens */
                        /* or a device that didn't see activity after passing */
                        /* a token (how lame!). */
                        /* Synchronize with the network. */
                        /* This action drops the token. */
                        Master_State = MSTP_MASTER_STATE_IDLE;
                    }
                    MSTP_Flag.ReceivedValidFrame = false;
                    transition_now = true;
                }
            }
            break;
            /* The DONE_WITH_TOKEN state either sends another data frame,  */
            /* passes the token, or initiates a Poll For Master cycle. */
        case MSTP_MASTER_STATE_DONE_WITH_TOKEN:
            /* SendAnotherFrame */
            if (FrameCount < Nmax_info_frames) {
                /* then this node may send another information frame  */
                /* before passing the token.  */
                Master_State = MSTP_MASTER_STATE_USE_TOKEN;
                transition_now = true;
            }
            /* Npoll changed in Errata SSPC-135-2004 */
            else if (TokenCount < (Npoll - 1)) {
                if ((MSTP_Flag.SoleMaster == true) &&
                    (Next_Station != next_this_station)) {
                    /* SoleMaster */
                    /* there are no other known master nodes to */
                    /* which the token may be sent 
                       (true master-slave operation).  */
                    FrameCount = 0;
                    TokenCount++;
                    Master_State = MSTP_MASTER_STATE_USE_TOKEN;
                    transition_now = true;
                } else {
                    /* SendToken */
                    /* Npoll changed in Errata SSPC-135-2004 */
                    /* The comparison of NS and TS+1 
                       eliminates the Poll For Master
                       if there are no addresses between 
                       TS and NS, since there is no 
                       address at which a new master node 
                       may be found in that case. */
                    TokenCount++;
                    /* transmit a Token frame to NS */
                    MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
                        This_Station, NULL, 0);
                    RetryCount = 0;
                    EventCount = 0;
                    Master_State = MSTP_MASTER_STATE_PASS_TOKEN;
                }
            } else if (next_poll_station == Next_Station) {
                if (MSTP_Flag.SoleMaster == true) {
                    /* SoleMasterRestartMaintenancePFM */
                    Poll_Station = next_next_station;
                    MSTP_Send_Frame(FRAME_TYPE_POLL_FOR_MASTER, Poll_Station,
                        This_Station, NULL, 0);
                    /* no known successor node */
                    Next_Station = This_Station;
                    RetryCount = 0;
                    TokenCount = 1;     /* changed in Errata SSPC-135-2004 */
                    /* EventCount = 0; removed in Addendum 135-2004d-8 */
                    /* find a new successor to TS */
                    Master_State = MSTP_MASTER_STATE_POLL_FOR_MASTER;
                } else {
                    /* ResetMaintenancePFM */
                    Poll_Station = This_Station;
                    /* transmit a Token frame to NS */
                    MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
                        This_Station, NULL, 0);
                    RetryCount = 0;
                    TokenCount = 1;     /* changed in Errata SSPC-135-2004 */
                    EventCount = 0;
                    Master_State = MSTP_MASTER_STATE_PASS_TOKEN;
                }
            } else {
                /* SendMaintenancePFM */
                Poll_Station = next_poll_station;
                MSTP_Send_Frame(FRAME_TYPE_POLL_FOR_MASTER, Poll_Station,
                    This_Station, NULL, 0);
                RetryCount = 0;
                Master_State = MSTP_MASTER_STATE_POLL_FOR_MASTER;
            }
            break;
            /* The PASS_TOKEN state listens for a successor to begin using */
            /* the token that this node has just attempted to pass. */
        case MSTP_MASTER_STATE_PASS_TOKEN:
            if (Timer_Silence() <= Tusage_timeout) {
                if (EventCount > Nmin_octets) {
                    /* SawTokenUser */
                    /* Assume that a frame has been sent by 
                       the new token user.  */
                    /* Enter the IDLE state to process the frame. */
                    Master_State = MSTP_MASTER_STATE_IDLE;
                    transition_now = true;
                }
            } else {
                if (RetryCount < Nretry_token) {
                    /* RetrySendToken */
                    RetryCount++;
                    /* Transmit a Token frame to NS */
                    MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
                        This_Station, NULL, 0);
                    EventCount = 0;
                    /* re-enter the current state to listen for NS  */
                    /* to begin using the token. */
                } else {
                    /* FindNewSuccessor */
                    /* Assume that NS has failed.  */
                    Poll_Station = next_next_station;
                    /* Transmit a Poll For Master frame to PS. */
                    MSTP_Send_Frame(FRAME_TYPE_POLL_FOR_MASTER, Poll_Station,
                        This_Station, NULL, 0);
                    /* no known successor node */
                    Next_Station = This_Station;
                    RetryCount = 0;
                    TokenCount = 0;
                    /* EventCount = 0; removed in Addendum 135-2004d-8 */
                    /* find a new successor to TS */
                    Master_State = MSTP_MASTER_STATE_POLL_FOR_MASTER;
                }
            }
            break;
            /* The NO_TOKEN state is entered if Timer_Silence() 
               becomes greater than Tno_token, indicating that 
               there has been no network activity for that period 
               of time. The timeout is continued to determine  
               whether or not this node may create a token. */
        case MSTP_MASTER_STATE_NO_TOKEN:
            my_timeout = Tno_token + (Tslot * This_Station);
            if (Timer_Silence() < my_timeout) {
                if (EventCount > Nmin_octets) {
                    /* SawFrame */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -