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

📄 ioread.cpp

📁 一个OPC服务器开发的源代码。结构清晰
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/**************************************************************************
 *                                                                        *
 * 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 + -