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

📄 udprotcl.c

📁 工业组态软件modbus驱动源代码, 包括帮助文件.共享.
💻 C
📖 第 1 页 / 共 5 页
字号:
                }
                /* clean up symbol table locks, delete write message */
                UdprotDeleteWriteMsg (lpMsg, lpTopic);
                /* get pointer to next message, if any */
                lpMsg = (LPUDMSG) FindNextItem (&message_scanner);
            }
        }
    }
} /* UdprotSetSlowPollMode */

/***********************************************************************/
/* check and update the STATUS on the topic (if necessary) */

static
void
WINAPI
UdprotCheckAndUpdateStatus (LPSTAT lpTopic)
{
    PTVALUE   ptValue;
    PTTIME    ptTime;
    PTQUALITY ptQuality;
#ifdef DEBUG_CALL_TRAFFIC
    char      szDateTime [81];
#endif

    if (lpTopic->statStatusActive && lpTopic->statStatusDue) {
        /* indicate error if STATUS data base handle not defined */
        assert(lpTopic->statHdbStatus);
        /* set up date/time stamp and quality flags */
#ifdef WIN32
        DbGetGMTasFiletime( &ptTime );
#else
        ptTime.dwLowDateTime = 0;
        ptTime.dwHighDateTime = 0;
#endif
        ptQuality = WWQ_GOOD;
        /* get STATUS value */
        ptValue.disc = (DISC) (!lpTopic->statFailed);
#ifdef DEBUG_CALL_TRAFFIC
        if (Verbose)
            debug (GetString (STRUSER + 150),
            /* "DbNewVTQFromDevice ( 0x%08lX, 0x%08lX, 0x%08lX, %Fs, 0x%04lX ) %s" */
                   (long) lpTopic->statIdLogDev, (long) lpTopic->statHdbStatus,
                   (long) ptValue.disc, UdprotGetDateTimeString((LPPTTIME) &ptTime, szDateTime),
                   (long) ptQuality, " STATUS");
#endif
        /* report new STATUS value */
        DbNewVTQFromDevice(lpTopic->statIdLogDev,
                           (HDB) lpTopic->statHdbStatus,
                           ptValue, &ptTime, ptQuality);
        /* clear STATUS due flag */
        lpTopic->statStatusDue = FALSE;
    }
} /* UdprotCheckAndUpdateStatus */

/***********************************************************************/
/** delete current write message on indicated port **/

static
void
WINAPI
UdprotDeleteCurWriteMsg(LPPORT lpPort)
{
    LPUDMSG         lpMsg;
    LPSTAT          lpTopic;

    /* get pointer to current message */
    lpMsg = lpPort->mbCurMsg;
    if (!lpMsg) {
        /* no message, just return */
        return;
    }
    if (lpMsg->mmDue) {
        /* message not due, just return */
        return;
    }

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

    /* indicate error if message is not first in list */
    assert((LPUDMSG) lpTopic->statWriteMsgList.first_item.ptr == lpMsg);

    /* clean up symbol table locks, delete write message */
    UdprotDeleteWriteMsg(lpMsg, lpTopic);

    /* ensure there is no current message for port or station */
    lpPort->mbCurMsg = (LPUDMSG)NULL;
    lpTopic->statCurMsg = (LPUDMSG)NULL;
} /* UdprotDeleteCurWriteMsg */

/***********************************************************************/
/** clean up symbol table locks,
    delete write message for indicated station **/

static
void
WINAPI
UdprotDeleteWriteMsg(LPUDMSG lpMsg, LPSTAT lpTopic)
{
    SYMPTR          lpSymEnt;
    CHAINSCANNER    symbol_scanner;

    if ((lpMsg == (LPUDMSG) NULL) || (lpTopic == (LPSTAT) NULL)) {
        /* no message or no station, just return */
        return;
    }

    /* handle all symbol entries associated with the write */
    if (lpMsg->mmFirstSym >= SYM_OFFSET) {
        /* get pointer to first symbol entry associated with the write */
        lpSymEnt = (SYMPTR) GetExtArrayMemberPtr (&lpTopic->statSymTab,
                                (lpMsg->mmFirstSym - SYM_OFFSET));
        /* set up scanner, start with this symbol in the list of used symbols */
        if (lpSymEnt != (SYMPTR) NULL)
            lpSymEnt = (SYMPTR) FindItemStartingAt ((LPCHAINLINK) lpSymEnt,
                                                    &lpTopic->statSymUsed,
                                                    SCAN_FROM_HEAD,
                                                    NULL, NULL, &symbol_scanner);
        /* decrement lock count for all symbols in this message */
        while (lpSymEnt != (SYMPTR) NULL) {
            if (lpSymEnt->msLockCt > 0) {
                /** Decrement the lock count if it is not zero.
                    When it becomes zero, reads will again be able
                    to report values to the client. **/
                lpSymEnt->msLockCt--;
            }
            /* check whether this is the last symbol for the message */
            if ((lpSymEnt->msIndex + SYM_OFFSET) == lpMsg->mmLastSym) {
                /* done, force end of loop */
                lpSymEnt = (SYMPTR) NULL;
            } else {
                /* get pointer to next symbol, if any */
                lpSymEnt = (SYMPTR) FindNextItem (&symbol_scanner);
            }
        }
    }

    /* remove this message from the list and free its memory */
    DeleteItem (&lpTopic->statWriteMsgList,
                (LPCHAINLINK) lpMsg, DeleteMessageItem);
} /* UdprotDeleteWriteMsg */

/***********************************************************************/
/** Extract item from data base, report value.
    Called from UdprotExtractReadData( )       **/

void
WINAPI
UdprotExtractDbItem(LPPORT lpPort,
                    SYMPTR lpSymEnt,
                    LPUDMSG lpMsg,
                    WORD byteOffset,
                    WORD bitOffset,
                    LPPTTIME lpPtTime)
{
    PTVALUE         ptValue;
    PTQUALITY       ptQuality;
    DISC            bitValue;
    BYTE FAR       *lpBuf;
    WORD            count;
    int             iStrLen, i;
    BYTE            pStrBuf[UD_MAX_READ_LENGTH];
    INTG            given_value, tmp;
    BOOL            badBCDRead;
    union {
           long     l;
           DWORD    dw;
           INTG     i;
           WORD     w;
           REAL     r;
           BYTE     b[4];
          } num;
#ifdef DEBUG_CALL_TRAFFIC
    char      szDateTime [81];
#endif

    /* set default quality to GOOD */
    ptQuality = WW_SQ_GOOD;

    /*
     * If the point is "locked" - just return.
     * A point is "locked" by the driver when a write is pending.
     */
    if (lpSymEnt->msLockCt) {
        return;
    }

    /*
     * Beware of data alignment issues on NT platforms here.
     * Variables and structures must be aligned on their natural boundaries.
     * Thus, use _fmemcpy below rather than direct assigns to words, reals.
     */

    /* clear holder for new data */
    memset (&num, 0, sizeof(num));

    /* get pointer to response buffer */
    lpBuf = (BYTE FAR *) &lpPort->mbRspBuffer[byteOffset];

    /* get and save data quality flags for previous read, clear flags */
    badBCDRead = lpSymEnt->msBadBCDRead;
    lpSymEnt->msBadBCDRead = FALSE;

    /* handle data according to type */
    switch (lpSymEnt->msDdeType) {

    case PTT_DISCRETE:
        /* extract discrete value from buffer */
        switch (lpSymEnt->msSubType) {
            case PLCS_BITP:
                /* get bit from a word value (see below about byte switching) */
                num.b[1] = *lpBuf++;
                num.b[0] = *lpBuf++;
                bitOffset = (WORD) (lpSymEnt->msBitPos - 1);
                bitValue = (DISC) (((num.w & bitMask[bitOffset]) == 0) ? 0 : 1);
                break;
            default:
                /* get bit from a discrete value */
                bitValue = (DISC)((((BYTE) *lpBuf & bitMask[bitOffset]) == 0) ? 0 : 1);
                break;
        } /* switch */
        ptValue.disc = bitValue;
        /* report new discrete value */
#ifdef DEBUG_CALL_TRAFFIC
        if (Verbose)
            debug (GetString (STRUSER + 150),
            /* "DbNewVTQFromDevice ( 0x%08lX, 0x%08lX, 0x%08lX, %Fs, 0x%04lX ) %s"*/
                   (long) lpMsg->mmIdLogDev, (long) lpSymEnt->msDbHnd,
                   (long) ptValue.disc, UdprotGetDateTimeString(lpPtTime, szDateTime),
                   (long) ptQuality, "");
#endif
        DbNewVTQFromDevice(lpMsg->mmIdLogDev, lpSymEnt->msDbHnd, ptValue, lpPtTime, ptQuality);
        break;

    case PTT_INTEGER:
        /***********************************************************\
           For most ASCII protocols the received bytes must be
           switched; therefore, following conversion is correct.
           For most binary protocols, the received bytes do not
           need to be switched and the following two lines would
           be replaced with:
           num.b[0] = *lpBuf++;        /+ get lsbyte +/
           num.b[1] = *lpBuf++;        /+ get msbyte +/
        \***********************************************************/
        num.b[1] = *lpBuf++;         /* get msbyte */
        num.b[0] = *lpBuf++;         /* get lsbyte */
        switch (lpSymEnt->msSubType) {
            case PLCS_SIGNED:
                if (num.w & 0x8000) {
                    /* extend sign */
                    num.l |= 0xFFFF0000;
                }
                break;
            case PLCS_BCD:
                /* convert from BCD to binary */
                given_value = num.i;
                tmp = UdprotCvtBCDToBin ((WORD) given_value);
                if (given_value != (INTG) UdprotCvtBinToBCD ((WORD) tmp)) {
                    /* set special value */
                    tmp = 19999;
                    /* flag data quality error */
                    ptQuality = WW_SQ_NOCONVERT;
                    if (ShowingErrors && (!badBCDRead)) {
                        /* have logger show error */
                        debug ("BCD read value 0x%04lX invalid for PlcDataType=%d, "
                               "Addr=0x%04lX.  Returning %ld.",
                               (long) given_value, (int) lpSymEnt->msPlcDataType,
                               (long) lpSymEnt->msAddr1, (long) tmp);
                    }
                    /* flag data quality error */
                    lpSymEnt->msBadBCDRead = TRUE;
                }
                num.i = tmp;
                break;
            case PLCS_DWORD:
                /* move first word to msword, get next word as lsword */
                num.b[3] = num.b[1];
                num.b[2] = num.b[0];
                num.b[1] = *lpBuf++;
                num.b[0] = *lpBuf++;
                break;
        } /* switch */
        ptValue.intg = num.i;
        /* report new numerical value */
#ifdef DEBUG_CALL_TRAFFIC
        if (Verbose)
            debug (GetString (STRUSER + 150),
            /* "DbNewVTQFromDevice ( 0x%08lX, 0x%08lX, 0x%08lX, %Fs, 0x%04lX ) %s"*/
                   (long) lpMsg->mmIdLogDev, (long) lpSymEnt->msDbHnd,
                   (long) ptValue.intg, UdprotGetDateTimeString(lpPtTime, szDateTime),
                   (long) ptQuality, "");
#endif
        DbNewVTQFromDevice(lpMsg->mmIdLogDev, lpSymEnt->msDbHnd, ptValue, lpPtTime, ptQuality);
        break;

    case PTT_REAL:
        /***********************************************************\
            For most ASCII protocols the received bytes must be
            switched; therefore, following conversion is correct.
            For most binary protocols, the received bytes do not
            need to be switched and the following two lines would
            be replaced with:
            num.b[0] = *lpBuf++;
            num.b[1] = *lpBuf++;
            num.b[2] = *lpBuf++;
            num.b[3] = *lpBuf++;
        \***********************************************************/
		// 3/6/2000 modify by Chen jun
		// modify real type data
        num.b[1] = *lpBuf++;
        num.b[0] = *lpBuf++;
        num.b[3] = *lpBuf++;
        num.b[2] = *lpBuf++;
        _fmemcpy( &ptValue.real, &num, sizeof(ptValue.real) );

        /* report new real value */
#ifdef DEBUG_CALL_TRAFFIC
        if (Verbose)
            debug (GetString (STRUSER + 150),
            /* "DbNewVTQFromDevice ( 0x%08lX, 0x%08lX, 0x%08lX, %Fs, 0x%04lX ) %s"*/
                   (long) lpMsg->mmIdLogDev, (long) lpSymEnt->msDbHnd,
                   (long) ptValue.intg, UdprotGetDateTimeString(lpPtTime, szDateTime),
                   (long) ptQuality, "");
#endif
        DbNewVTQFromDevice(lpMsg->mmIdLogDev, lpSymEnt->msDbHnd, ptValue, lpPtTime, ptQuality);
        break;

    case PTT_STRING:
        /***********************************************************\
           Move the string to be sent into pStrBuf.
           Make sure that string has a terminating null character.

⌨️ 快捷键说明

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