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

📄 udprotcl.c

📁 工业组态软件modbus驱动源代码, 包括帮助文件.共享.
💻 C
📖 第 1 页 / 共 5 页
字号:
        \***********************************************************/
        count = LimitStringLength (lpSymEnt->msAddr1, lpSymEnt->msCount,
                                   (WORD) lpSymEnt->msNumBytes, TRUE);
        if (count < lpSymEnt->msCount) {
            /* indicate string is truncated */
            ptQuality = WW_SQ_CLAMPHI;
        }
        iStrLen = count * lpSymEnt->msNumBytes;
        switch (lpSymEnt->msSubType)
        {
            case PLCS_STRC:
            case PLCS_STRB:
            case PLCS_STR_:
                /* just copy the string */
                _fstrncpy ((LPSTR) pStrBuf, (LPSTR) lpBuf, (size_t) iStrLen);
                break;
            case PLCS_STRP:
                /* first byte is string length, get it, limit if needed */
                i = (int) ((unsigned char) lpBuf[0]);
                if ((i < 0) || (iStrLen <= i))
                {
                    i = iStrLen - 1;
                    /* indicate string is truncated */
                    ptQuality = WW_SQ_CLAMPHI;
                }
                /* copy remainder of string, terminate it */
                _fstrncpy ((LPSTR) pStrBuf, (LPSTR) &lpBuf[1], (size_t) i);
                pStrBuf[i] = '\0';
                break;
        } /* switch */
        /* Make sure the string is null-terminated */
        pStrBuf [iStrLen] = '\0';
        /* report new string value */
#ifdef DEBUG_CALL_TRAFFIC
        if (Verbose)
            debug (GetString (STRUSER + 151),
                   /* "DbNewVTQFromDevice ( 0x%08lX, 0x%08lX, 0x%08lX, %Fs, 0x%04lX ) %s = \"%s\"" */
                   (long) lpMsg->mmIdLogDev, (long) lpSymEnt->msDbHnd,
                   (long) ptValue.intg, UdprotGetDateTimeString(lpPtTime, szDateTime),
                   (long) ptQuality, "", pStrBuf);
#endif
        ptValue = StrValInitialString ((LPSTR) pStrBuf);
        DbNewVTQFromDevice(lpMsg->mmIdLogDev, lpSymEnt->msDbHnd, ptValue, lpPtTime, ptQuality);
        break;

    default:
        break;
    }
} /* UdprotExtractDbItem */

/***********************************************************************/
/** Extract data from response to read message.
    The rspBuffer has the last message received from the communication port.
    This function will extract the data from the response,
    put it in ptValue, and send the data to the Toolkit database.
    It is up to the Toolkit to detect whether the value has changed.
    If it has, the Toolkit will relay the data to any clients who
    are interested in the new value.
    Called from ProcessValidResponse( )      **/

void
WINAPI
UdprotExtractReadData(LPPORT lpPort,
                      LPSTAT lpTopic,
                      LPUDMSG lpMsg)
{
    LPEXTARRAY      lpSymbol_table;
    SYMPTR          lpSymEnt;
    BOOL            bHaveDateTimeStamp;
    PTTIME          ptTime;
    WORD            startAddr, myAddr, count;
    unsigned long   firstSymIdx, lastSymIdx;
    WORD            numBytes;
    WORD            blockStart, blockOffset, bitOffset;
    BOOL            done;
    CHAINSCANNER    symbol_scanner;
    ACTIVE_CHECK    compValue;

    /* get pointer to symbol table */
    lpSymbol_table = &lpTopic->statSymTab;
    if (lpSymbol_table == (LPEXTARRAY) NULL) {
        /* cannot access symbol table structure, just return */
        return;
    }

    /* indicate no date/time stamp set up yet */
    bHaveDateTimeStamp = FALSE;

    /*
     * For each symbol table entry in this message
     * extract the data from the message.
     */

    /********************************************************************\
        Set blockStart to the BYTE offset of the data block from the
        beginning of the message as shown below.
        Define the constant shown to have the required value.
    \********************************************************************/

    blockStart = UD_BLOCK_DATA_START;

    /* get address of first point in message */
    startAddr = lpMsg->mmStartAddr;

    /* set up comparison value */
    compValue.lpMsg       = lpMsg;             /* pointer to this message */
    compValue.finalHandle = lpMsg->mmLastSym;  /* last symbol in message */
    compValue.SymHandle   = 0;                 /* no symbol found yet */

    /* get handles for first and last symbols in this message */
    firstSymIdx = lpMsg->mmFirstSym;
    lastSymIdx  = lpMsg->mmLastSym;

    /* get pointer to first symbol entry referenced by the message */
    lpSymEnt = (SYMPTR) NULL;
    if (firstSymIdx >= SYM_OFFSET) {
        /* valid symbol handle, get pointer to symbol entry */
        lpSymEnt = (SYMPTR) GetExtArrayMemberPtr (lpSymbol_table,
                                               firstSymIdx - SYM_OFFSET);
        /* get first active symbol referenced by this message */
        /* Note:  if found, compValue.SymHandle will be non-zero */
        if (lpSymEnt != (SYMPTR) NULL)
            lpSymEnt = (SYMPTR) FindItemStartingAt ((LPCHAINLINK) lpSymEnt,
                                                    &lpTopic->statSymUsed,
                                                    SCAN_FROM_HEAD,
                                                    IsActiveOnMessage,
                                                    &compValue,
                                                    &symbol_scanner);
    }

    /* scan through range of symbols covered by this message */
    done = FALSE;
    while ((!done) && (lpSymEnt != (SYMPTR) NULL)) {
        /* check whether symbol is active and polled by this message */
        if (compValue.SymHandle != 0) {
            /* match found, get parameters from symbol table entry */
            myAddr   = lpSymEnt->msAddr1;
            count    = lpSymEnt->msCount;
            numBytes = (WORD) lpSymEnt->msNumBytes;

            /* check whether already have date/time stamp */
            if (!bHaveDateTimeStamp) {
                /* set up date/time stamp */
#ifdef WIN32
                DbGetGMTasFiletime( &ptTime );
#else
                ptTime.dwLowDateTime = 0;
                ptTime.dwHighDateTime = 0;
#endif
                /* indicate date/time stamp ready */
                bHaveDateTimeStamp = TRUE;
            }

            /* determine starting point and length of data to convert */
            switch (lpMsg->mmDataType) {
            case PTT_DISCRETE:
                /***********************************************************\
                    Compute the blockOffset and bitOffset, which are
                    dependent on the message format for this protocol.
                    The following example calculates these values where:

                    'blockStart' is BYTE offset from the beginning of
                                 the message for the data block;
                    'startAddr'  is the first bit number in the data block
                    'myAddr'     is the bit number for this symbol
                    8-bits per BYTE is assumed
                \***********************************************************/

                blockOffset = (WORD) (blockStart + (myAddr-startAddr) / 8L);
                bitOffset   = (WORD) ((myAddr-startAddr) % 8);
                break;
            default:
                /*
                 * The default section is for the PTT_INTEGER
                 * and PTT_REAL data types.
                 */
                /***********************************************************\
                    Compute the blockOffset and bitOffset, which are
                    dependent on the message format for this protocol.
                    The following example calculates these values where:

                    'blockStart' is BYTE offset from the beginning of
                                 the message for the data block;
                    'startAddr'  is the first symbol address in the data
                                 block
                    'myAddr'     is the symbol address for this symbol
                    'numBytes'   is the number of BYTES in the message
                                 for each "cell"
                    8-bits per BYTE is assumed
                \***********************************************************/

                blockOffset = (WORD) (blockStart + numBytes * (myAddr-startAddr));
                bitOffset   = 0;
                break;
            }
            /* convert message segment to value and report it */
            UdprotExtractDbItem(lpPort, lpSymEnt, lpMsg, blockOffset, bitOffset, &ptTime);
        }
        /* check whether to continue scanning */
        if (lpSymEnt->msIndex + SYM_OFFSET == lastSymIdx) {
            /* last symbol handle for message, exit */
            done = TRUE;
        } else {
            /* get pointer to next active symbol on message, if any */
            lpSymEnt = (SYMPTR) FindNextItem (&symbol_scanner);
        }
    }
} /* UdprotExtractReadData */

/***********************************************************************/
/** Process validated response back from the device **/

void
WINAPI
ProcessValidResponse(LPPORT   lpPort)
{
    LPUDMSG         lpMsg;
    LPSTAT          lpTopic;
    BYTE FAR       *rsp;

    /* get pointer to current message, if any */
    lpMsg = lpPort->mbCurMsg;
    if (lpMsg == (LPUDMSG) NULL) {
        /* no current message, just return */
        return;
    }

    /* check whether message has changed */
    if (lpMsg->mmChanged) {
        /* If was changed after it was written -- ignore the response */
        return;
    }

    /* get pointer to corresponding station */
    lpTopic = lpMsg->mmTopic;
    if (lpTopic == (LPSTAT) NULL) {
        /* unable to access station structure, just return */
        return;
    }

    /* reset station retry limits */
    lpTopic->statRetries = TOPIC_CONSEC_FAILURE_LIMIT;
    lpTopic->statPortRetries = TOPIC_NORMAL_RETRIES;

    /*********************************************************\
      How messages are handled may depend on the protocol.
      The following example handles reads and writes
      and also processes error responses from the device.
    \*********************************************************/

    /* check type of message received */
    rsp = (BYTE FAR *) lpPort->mbRspBuffer;
    switch (*rsp) {
        case 0x00:    /* error message */
            /* indicate error */
            UdprotSetMsgQuality (lpTopic, lpMsg, WW_SQ_NOACCESS);
            if (ShowingErrors) {
                debug ("Error message received.");
                showReceivedData (lpPort);
            }
            break;
        default:
            /* check type of message */
            if (lpMsg->mmRead) {
                /* was a "read" -- extract data from response and report it */
                UdprotExtractReadData(lpPort, lpTopic, lpMsg);
            }
            break;
    } /* switch */

    /* check type of message */
    if (!lpMsg->mmRead) {
        /* was a "write" -- delete the write message */
        UdprotDeleteCurWriteMsg(lpPort);
    }

    /* check station status, ensure we're out of slow poll mode */
    UdprotSetTopicStatus (lpPort, lpTopic, FALSE);
} /* ProcessValidResponse */

/***********************************************************************/
/** Validate the received message, ensure it is in binary form
    return TRUE if message is OK **/

static
BOOL
WINAPI
UdprotValidMessage(LPPORT   lpPort)
{
    /*******************************************************************\
       The contents of this routine are protocol dependent.
       Validate the frame format i.e. the checksum/CRC, start BYTE,
       end BYTE, message contents, etc...

       The following example uses the same validation routine used
       by the PLC simulator itself to verify that the message contains
       the right header, tail, characters, length, and checksum.
    \*******************************************************************/

    BOOL      valid;
    int       len;

    /* check whether message is valid format */
    valid = IsCommandValid ((LPSTR) &lpPort->mbRspBuffer[0], lpPort->mbRspIndex);

    /* if message is valid, convert hex ASCII to binary bytes as necessary */
    if (valid) {
        if (!lpPort->mbMsgInBinary) {
            /* convert message to binary, determine whether result is valid */
            len = lpPort->mbRspIndex;
            valid = GetMsgAsBinary ((LPSTR) &lpPort->mbRspBuffer[0], &len);
            lpPort->mbRspIndex = len;
            /* indicate message in binary */
            lpPort->mbMsgInBinary = TRUE;
        }
    }

    return (valid);
} /* UdprotValidMessage */

/***********************************************************************/
/** Validate the frame and call ProcessValidResponse( ) if OK.
    Called from DoProtocol( )      **/

void
WINAPI
UdprotProcessResponse(LPPORT   lpPort)
{
    /******************************************************************\
      If the protocol for this driver uses ASCII characters, the
      contents of lpPort->mbRspBuffer must be converted to binary now.
      All code after this point assumes that lpPort->mbRspBuffer is
      binary.

      Example:
        len = lpPort->mbRspIndex;

⌨️ 快捷键说明

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