📄 ioread.cpp
字号:
/**************************************************************************
* *
* Light OPC Server development library *
* *
* Copyright (c) 2000 Timofei Bondarenko *
*
LightOPCGroup::IOPC[A]SyncIO::Read() methods
**************************************************************************/
#include <opcerror.h>
#include "privopc.h"
#include LO_OLE_ERRORS_h /*CONNECT_E_NOCONNECTION*/
/* OPC-DA v2.04:
4.3 p.22:
It is expected that most clients will use either Reads or Subscriptions for
a particular group but not both. If both are used then there is some interaction
between Reads and Subscriptions in that anything sent to the client as a result
of a 'read' is also considered to be the 'last value sent'.
4.5.1.8 p.72
There are basically three ways to get data into a client
(ignoring the 'old' IDataObject/IAdviseSink).
IOPCSyncIO::Read (from cache or device)
IOPCAsyncIO2::Read (from device)
IOPCCallback::OnDataChange() (exception based)
which can also be triggered by IOPCAsyncIO2::Refresh.
In general the three methods operate independently without 'side effects' on each other.
*****************/
/*********************************** LightOPCGroup::IOPCSyncIO stuff **************************/
#if 0
static unsigned extract_itemstate_from_req(unsigned count,
HRESULT *err,
OPCITEMSTATE *ist,
VARIANT *vars,
VARTYPE *vtype,
FILETIME *timestamp,
WORD *quality)
{
unsigned items_ok;
for(items_ok = 0; count--; err++, ist++, vars++, vtype++)
{
HRESULT hrr;
ist->wQuality = *quality++;
ist->ftTimeStamp = *timestamp++;
hrr = *err;
if (SUCCEEDED(hrr))
{
VARTYPE vt;
if ((vt = *vtype) != VT_EMPTY &&
vt != V_VT(vars) &&
S_OK != (hrr = VariantChangeType(vars, vars, 0, vt)))
{
LO_E_BADTYPE_QUAL(hrr, *err, ist->wQuality);
}
else items_ok++;
ist->vDataValue = *vars;
VARIANTINIT(vars);
}
}
return items_ok;
}
#endif
static HRESULT extract_itemstate_from_prim(unsigned count,
HRESULT *err,
OPCITEMSTATE *ist,
OPCHANDLE *phServer,
LightOPCGroup *grp,
const loCallerx *cctx)
{
loService *se = cctx->cactx.ca_se;//grp->owner->se;
loTagEntry *tags = se->tags;
int andActive = grp->Active? ~0: 0;
HRESULT master_err = S_OK;
LightOPCItem *it;
if (andActive/* | from_device*/) lw_rw_rdlock(&se->lkPrim);
for(; count--; err++, ist++, phServer++)
if (!(it = grp->by_index(*phServer)))
{ *err = OPC_E_INVALIDHANDLE; master_err = S_FALSE; continue; }
else
{
loTagEntry *te = &tags[it->tid];
// irs->wReserved = 0;
ist->hClient = it->hClient;
#if 0 != LO_CHECK_RIGHTS
if (!(OPC_READABLE & te->attr.taRights))
{ *err = OPC_E_BADRIGHTS; master_err = S_FALSE; continue; }
else
#endif
if (!(andActive & it->bActive /*| from_device*/))
{
ist->wQuality = OPC_QUALITY_OUT_OF_SERVICE;
*err = LO_E_NOTACTIVE;
master_err = S_FALSE;
continue;
}
else
{
HRESULT hrr;
ist->ftTimeStamp = te->prim.tsTime;
ist->wQuality = te->prim.tsQuality;
*err = hrr = te->prim.tsError;
if (S_OK != hrr) master_err = S_FALSE;
#ifdef VAR_CHANGETYPE
hrr = VAR_CHANGETYPE(&ist->vDataValue, &te->primValue,
it->vtRequestedDataType);
#else
switch(it->convtype)
{
case loCONV_CHANGE:
hrr = VARIANTCHANGE(&ist->vDataValue,
&te->primValue,
grp->grLCID, cctx->cta.vc_tfl,
it->vtRequestedDataType);
break;
case loCONV_COPY:
hrr = VariantCopy(&ist->vDataValue,
&te->primValue);
break;
case loCONV_ASSIGN:
ist->vDataValue = te->primValue;
continue;
hrr = S_OK;
break;
case loCONV_CONVERT:
{
HRESULT thr;
loTagPair tp;
tp.tpTi = it->tid;
tp.tpAP = it->AcPath;
tp.tpRt = te->attr.taRt;
se->driver.ldConvertTags(&cctx->cactx, 1, &tp,
&ist->vDataValue, &ist->wQuality, err,
&master_err, &thr, &te->primValue,
&it->vtRequestedDataType, grp->grLCID);
continue;
hrr = S_OK;
}
break;
}
#endif
if (hrr != S_OK)
{
LO_E_BADTYPE_QUAL(hrr, *err, ist->wQuality);
master_err = S_FALSE;
}
} /* active */
} /* handle */
/* end of for() */
if (andActive /*| from_device*/) lw_rw_unlock(&se->lkPrim);
return master_err;
}
/************************************************************************/
STDMETHODIMP LightOPCGroup::Read(OPCDATASOURCE dwSource,
DWORD dwCount,
OPCHANDLE *phServer,
OPCITEMSTATE **ppItemValues,
HRESULT **ppErrors)
{
HRESULT hr = S_OK, master_err = S_OK;
OPCITEMSTATE *ist = 0;
HRESULT *err = 0;
unsigned items_ok = 0;
LO_CHECK_STATEz2("SyncIO:Read", ppItemValues, ppErrors);
UL_TRACE((LOG_GRH("SyncIO:Read(%u/%u)..."), dwSource, dwCount));
if (!phServer || !ppItemValues || !dwCount ||
dwSource != OPC_DS_DEVICE && dwSource != OPC_DS_CACHE)
{ hr = E_INVALIDARG; goto Return; }
err = (HRESULT*)loComAlloc(dwCount * sizeof(HRESULT));
if (ist = (OPCITEMSTATE*)loComAlloc(dwCount * sizeof(OPCITEMSTATE)))
{
memset(ist, 0, dwCount * sizeof(OPCITEMSTATE));
#if 0 != LO_INIT_VARIANT
for(ii = dwCount; ii--;) VARIANTINIT(&ist[ii].vDataValue);
#endif
}
if (!err || !ist) { hr = E_OUTOFMEMORY; goto Return; }
if (dwSource == OPC_DS_DEVICE) /* real device reading */
{
unsigned ii;
loService *se = owner->se;
loTagEntry *tags = se->tags;
loRequest *rq;
loTagPair *tpl;
// HRESULT *errors;
rq = lo_req_alloc(dwCount, loUPL_variant | loUPL_timestamp | loUPL_quality |
/*loUPL_errors |*/ loUPL_tagpair | loUPL_vartype);
if (!rq) { hr = E_OUTOFMEMORY; goto Return; }
rq->com_allocated = rq->upl.errors = err;
rq->operation = loRQ_OP_READ | loRQ_SYNC | loRQ_DEVICE;
rq->group_key = ServerHandle;
rq->serv_key = owner->serv_key;
// memset(rq->upl.timestamp, 0, sizeof(FILETIME) * dwCount);
tpl = rq->upl.tagpair;
loTagPair_init(tpl, dwCount);
// errors = rq->upl.errors;
rq->upl.rctx = owner->ctxt;
lock_read();
rq->upl.rctx.cta.vc_lcid = grLCID;
if (owner->access_mode & (loAM_NOREAD_DEV|loAM_ERREAD_DEV))
{
if (owner->access_mode & loAM_NOREAD_DEV) rq->operation &= ~loRQ_DEVICE;
if (owner->access_mode & loAM_ERREAD_DEV)
{
unsigned ii;
for(ii = 0; ii < dwCount; ii++) err[ii] = OPC_E_BADRIGHTS;
goto Unlock;
}
}
for(ii = 0; ii < dwCount; ii++, tpl++)
{
LightOPCItem *it;
if (!(it = by_index(phServer[ii]))) err[ii] = OPC_E_INVALIDHANDLE;
else
{
loTagEntry *te = &tags[it->tid];
ist[ii].hClient = it->hClient;
#if 0 != LO_CHECK_RIGHTS
if (!(OPC_READABLE & te->attr.taRights)) err[ii] = OPC_E_BADRIGHTS;
else
#endif
{
err[ii] = S_OK;
tpl->tpTi = te->attr.taTi;
tpl->tpRt = te->attr.taRt;
tpl->tpAP = it->AcPath;
rq->upl.vartype[ii] = it->vtRequestedDataType;
rq->upl.quality[ii] = (WORD)it->convtype;
items_ok++;
}
}
}
Unlock:
unlock();
err = 0;
rq->upl.used = dwCount;
if (items_ok != dwCount) rq->upl.master_err = S_FALSE;
if (0 == items_ok)
{
// memcpy(err, rq->upl.errors, dwCount * sizeof(*err));
err = rq->upl.errors;
rq->com_allocated = 0;
lo_req_free(rq);
}
else if (rq = lo_req_put_sync(&owner->q_req, &owner->q_ret, rq))
{
#if 0
items_ok = extract_itemstate_from_req(dwCount, ist,
rq->upl.variant, rq->upl.timestamp, rq->upl.quality);
#else
VARIANT *vars = rq->upl.variant;
FILETIME *timestamp = rq->upl.timestamp;
WORD *quality = rq->upl.quality;
unsigned ii = dwCount;
while(ii--)
{
ist[ii].wQuality = quality[ii];
ist[ii].ftTimeStamp = timestamp[ii];
ist[ii].vDataValue = vars[ii];
VARIANTINIT(&vars[ii]);
}
master_err = rq->upl.master_err;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -