📄 udprotcl.c
字号:
}
/* 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 + -