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

📄 udprotcl.c

📁 工业组态软件modbus驱动源代码, 包括帮助文件.共享.
💻 C
📖 第 1 页 / 共 5 页
字号:
                                              NULL, NULL, &station_scanner);
        }
        if (lpTopic == (LPSTAT) NULL)
            /* cannot access station structure, exit */
            return;

        /*************************************/
        /* Check whether to report the value */
        /* of the reserved point STATUS      */
        /*************************************/

        UdprotCheckAndUpdateStatus (lpTopic);

        /*******************************/
        /* get pointer to message that */
        /* needs servicing, if any     */
        /*******************************/

        /* get pointer to first station write message, if any */
        wMsg = (LPUDMSG) FindFirstItem (&lpTopic->statWriteMsgList,
                                        SCAN_FROM_HEAD,
                                        NULL, NULL, &message_scanner);

        /* get pointer to current read message, if any */
        startMsg = lpTopic->statCurReadMsg;

        /* Set up scanner, find current read message on this station, if any
           If none, find the first read message on this station, if any */
        rMsg = (LPUDMSG) FindItemStartingAt ((LPCHAINLINK) startMsg,
                                             &lpTopic->statReadMsgList,
                                             SCAN_FROM_HEAD,
                                             NULL, NULL, &message_scanner);

        /* clear message pointer */
        lpMsg = (LPUDMSG)NULL;

        /* check whether to select write message or read message */
        if ((lpTopic->statConsecWrites > 0) &&
            (wMsg != (LPUDMSG) NULL)) {
            /* time to retry write message,
               decrement retry count and point to first station write message */
            lpTopic->statConsecWrites--;
            lpMsg = wMsg;
        } else {
            /* new message,
               initialize count and point to current station read message, if any */
            lpTopic->statConsecWrites = MAX_CONSEC_WRITES;
            if (startMsg != (LPUDMSG) NULL) {
                /* message available, point to it */
                lpMsg = startMsg;
            }
        }
        if (lpMsg == (LPUDMSG) NULL) {
            /* no message selected, point to first station read message, if any */
            lpMsg = startMsg = rMsg;
        }

        /************************************/
        /* check whether to service message */
        /* or switch to a different one     */
        /************************************/

        /* skip the station if delaying or if no messages */
        if ((lpTopic->statDelay == 0L) &&
            (lpMsg != (LPUDMSG) NULL)) {
            /* no delay and we have a message */
            /* check whether currently updating message */
            if (!lpMsg->mmRead) {
                /* not updating, write msg still in queue - do it again */
                found = TRUE;
            } else {
                /* updating, search through the read messages on this station */
                done = FALSE;
                while ((!found) && (!done)) {

                    /****************************************/
                    /* check whether to delete this message */
                    /****************************************/

                    if (lpMsg->mmActiveCt == 0) {
                        /* This message has no remaining active points.
                           It is just waiting to be deleted.   */
                        /* unchain the message, unlock it, and free its memory */
                        UdprotUnchainMsg(lpTopic, lpMsg);
                        UdprotFreeMsg(lpMsg);
                        /* check message pointer */
                        if (lpMsg == startMsg) {
                            /* this is the message we started with,
                               indicate that the message has been dropped */
                            startMsg = (LPUDMSG) NULL;
                        }
                    }

                    /*******************************/
                    /* get pointer to next message */
                    /*******************************/

                    /* check scanner for end of list */
                    if (GetScannerNextItem (&message_scanner) != NULL) {
                        /* get next item from message list */
                        lpMsg = (LPUDMSG) FindNextItem (&message_scanner);
                    } else {
                        /* end of list reached, wrap around to beginning of list */
                        lpMsg = (LPUDMSG) FindFirstItem (&lpTopic->statReadMsgList,
                                                         SCAN_FROM_HEAD,
                                                         NULL, NULL,
                                                         &message_scanner);
                    }

                    /**************************************************/
                    /* check whether ready message found or loop done */
                    /**************************************************/

                    if (lpMsg == (LPUDMSG) NULL) {
                        /* no more read messages, indicate we are done */
                        done = TRUE;
                    } else {
                        /* check message status */
                        if (lpMsg->mmDue && lpMsg->mmActiveCt) {
                            /* pending and active, indicate message found */
                            found = TRUE;
                        } else {
                            /* not ready, check whether we dropped a message */
                            if (startMsg == (LPUDMSG) NULL) {
                                /* dropped, set start pointer to this message */
                                startMsg = lpMsg;
                            } else {
                                /* not cleared, compare pointers */
                                if (startMsg == lpMsg) {
                                    /* back where we started, indicate we are done */
                                    done = TRUE;
                                }
                            }
                        }
                    }
                } /* while */
            }
        }

        /** stop search if ready message found
            or if we just finished checking the starting topic */
    } while ((!found) && (lpTopic != startTopic));

    if (found) {
        /* ready message found, set port to talk to indicated station */
        lpPort->mbCurTopic  = lpTopic;
        lpPort->mbCurMsg    = lpMsg;
        lpTopic->statCurMsg = lpMsg;
        if (lpMsg->mmRead) {
            /* currently updating message, set pointer */
            lpTopic->statCurReadMsg = lpMsg;
        }
        /* set port message pointers and status */
        lpPort->mbRetries   = lpTopic->statPortRetries;
        lpMsg->mmDue        = FALSE;
        lpMsg->mmChanged    = FALSE;
        lpPort->mbDoingRead = lpMsg->mmRead;
        /* check for periodic write message */
        if ((!lpMsg->mmRead) && (lpMsg->mmScanReload != 0)) {
            /* write message and periodic - currently not in there */
        }
        /* send the indicated query */
        UdprotSendQuery(lpPort, lpMsg);
    } else {
        /* no message found, indicate port is idle */
        lpPort->mbState = PROT_IDLE;
    }
} /* UdprotPoll */

/***********************************************************************/
/** Handle response error for indicated port.
    When an error is detected in the response message, retry up to
    retry limit.  Then set STATUS item to failed.  **/

void
WINAPI
UdprotHandleRspError(LPPORT  lpPort)
{
    LPSTAT          lpTopic;

    /* check the port for errors and log them */
    checkEvents (lpPort);

    if (ShowingErrors)
        /* display data received so far */
        showReceivedData(lpPort);
    if (bFlushOnError)
        /* flush port buffers */
        FlushPort (lpPort, (LPSTR) "");
    /* decrement message retries */
    if (lpPort->mbRetries > 0)
        lpPort->mbRetries--;
    /* check whether the message retry limit has been reached */
    if (lpPort->mbRetries > 0) {
        /* retry limit not yet reached, try again */
        UdprotSendQuery(lpPort, lpPort->mbCurMsg);
    } else {
        /* retry limit reached, indicate problem */
        /* mark this message as DUE, since it failed */
        lpTopic = lpPort->mbCurTopic;
        if (lpTopic) {
            /* decrement station retries */
            if (lpTopic->statRetries > 0)
                lpTopic->statRetries--;
            /* check whether the station retry limit has been reached */
            if (lpTopic->statRetries > 0) {
                /* retry limit not yet reached, set station for error delay */
                lpTopic->statDelay = (LONG) ERRORDELAY;
            } else {
                /* retries exhausted, set up for recovery mode */
                lpTopic->statPortRetries = TOPIC_RECOVERY_RETRIES;
                /* fail all stations on this port, since it had comm errors */
                /* (This includes setting into slow poll mode) */
                /* (It also includes deleting all writes if not retry indefinitely */
                UdprotFailStationTopics (lpPort);
            }
        }
        /* force poll of current station */
        UdprotPoll(lpPort);
    }
} /* UdprotHandleRspError */

/***********************************************************************/
/* fail all stations on indicated port */

static
void
WINAPI
UdprotFailStationTopics (LPPORT lpPort)
{
    LPSTAT       lpTopic;
    CHAINSCANNER station_scanner;

    /* check all stations */
    lpTopic = (LPSTAT) FindFirstItem (&lpPort->mbTopicList, SCAN_FROM_HEAD,
                                      NULL, NULL, &station_scanner);
    while (lpTopic != (LPSTAT) NULL) {
        /* indicate station has failed */
        UdprotSetTopicStatus (lpPort, lpTopic, TRUE);  /* true means failed */
        /* get pointer to next station, if any */
        lpTopic = (LPSTAT) FindNextItem (&station_scanner);
    }
} /* UdprotFailStationTopics */

/***********************************************************************/
/** set STATUS item in station structure
    return TRUE if status is changed **/

static
BOOL
WINAPI
UdprotSetTopicStatus (LPPORT lpPort, LPSTAT lpTopic, unsigned bFailed)
{
    BOOL changed;

    /* initialize return value */
    changed = FALSE;

    /* no change if pointer is NULL */
    if (lpTopic != (LPSTAT) NULL) {
        /* check current station status */
        if (lpTopic->statFailed != bFailed) {
            /* different from old status, update it */
            changed = TRUE;
            lpTopic->statFailed = bFailed;
            /* check whether station is active */
            if (lpTopic->statStatusActive) {
                /* active, indicate that station STATUS is due */
                lpTopic->statStatusDue = TRUE;
            }
            /* check whether new status is OK or failed */
            if (bFailed) {
                /* have logger indicate entering slow poll mode */
                debug ("Entering slow poll mode on topic \"%Fs\" on port %Fs.",
                       lpTopic->statTopicName, lpPort->mbPortName);
                /* report new STATUS value if necessary */
                UdprotCheckAndUpdateStatus (lpTopic);
                /* set "no communication" quality flags
                   for all points polled on topic */
                UdprotSetTopicQuality (lpTopic, WW_SQ_NOCOMM);
            } else {
                /* have logger indicate leaving slow poll mode */
                debug ("Leaving slow poll mode on topic \"%Fs\" on port %Fs.",
                       lpTopic->statTopicName, lpPort->mbPortName);
            }
        }
        /* check whether station is failed */
        if (bFailed) {
            /* set up slow poll mode */
            UdprotSetSlowPollMode (lpPort, lpTopic);
        }
    }
    /* indicate whether station status changed */
    return (changed);
} /* UdprotSetTopicStatus */

/***********************************************************************/
/* set up slow poll mode for station on indicated port */

static
void
WINAPI
UdprotSetSlowPollMode (LPPORT lpPort, LPSTAT lpTopic)
{
    long new_delay;
    LPUDMSG lpMsg;
    CHAINSCANNER message_scanner;

    /* no change if station pointer is NULL */
    if (lpTopic != (LPSTAT) NULL) {
        /* indicate station has failed */
        lpTopic->statRetries = 0;           /* indicate retries exhausted */
        /* set up for recovery mode */
        lpTopic->statPortRetries = TOPIC_RECOVERY_RETRIES;
        /* slow poll delay = 15 times update interval */
        /* constrain to reasonable range, though */
        new_delay = (long) SLOW_POLL_MULTIPLIER * lpTopic->statUpdatePeriod;
        if (new_delay > SLOW_POLL_MAX)
            new_delay = SLOW_POLL_MAX;
        if (new_delay < SLOW_POLL_MIN)
            new_delay = SLOW_POLL_MIN;
        lpTopic->statDelay = new_delay;

        /* delete all writes if not indefinitely retry */
        if (!IndefWriteRetry) {
            /* remove all writes from the list */
            lpMsg = (LPUDMSG) FindFirstItem (&lpTopic->statWriteMsgList,
                                             SCAN_FROM_HEAD,
                                             NULL, NULL, &message_scanner);
            while (lpMsg != (LPUDMSG) NULL) {
                /* check whether this is current message for port */
                if (lpMsg == lpPort->mbCurMsg) {
                    /* remove port reference to message */
                    lpPort->mbCurMsg = (LPUDMSG) NULL;
                    /* indicate port is idle */
                    lpPort->mbState = PROT_IDLE;

⌨️ 快捷键说明

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