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

📄 sample.cpp

📁 一个OPC服务器开发的源代码。结构清晰
💻 CPP
📖 第 1 页 / 共 3 页
字号:

/* OPTIONAL: example of DS_DEVICE read(). It enforces significant delay, 
  sufficient for view request's queueing and test the cancellation. */

loTrid ReadTags(const loCaller *ca,
                unsigned count, loTagPair taglist[],
                VARIANT *values, WORD *qualities,
                FILETIME *stamps, HRESULT *errs,
                HRESULT *master_err, HRESULT *master_qual,
                const VARTYPE vtypes[], LCID lcid)
{
  UL_TRACE((LOGID, "ReadTags( ) invoked"));
  Sleep(33333);                 /* just for Cancel() testing */
  return loDR_CACHED; /* perform actual reading from cache */
}

/* OPTIONAL: example of dynamic tag creation */

HRESULT AskItemID(const loCaller *ca, loTagId *ti, 
                  void **acpa, const loWchar *itemid, 
                  const loWchar *accpath, int vartype, int goal)  /* Dynamic tags */
{
  HRESULT hr = S_OK;
  VARIANT var;
  VariantInit(&var);  
  V_R4(&var) = 3;     /* God likes 3 */
  V_VT(&var) = VT_R4;

  UL_NOTICE((LOGID, "AskItemID %ls type = %u(0x%x)", itemid, vartype, vartype));

  if (VT_EMPTY != vartype) /* check conversion */
    hr = VariantChangeType(&var, &var, 0, vartype);

  if (S_OK == hr) /* we got a value of requested type */
    {
      int rv;
      rv =
        loAddRealTag_aW(ca->ca_se, ti, 0, itemid, 0,
                        OPC_READABLE | OPC_WRITEABLE, &var, 0, 100);
      if (rv)
        {
          if (rv == EEXIST) *ti = 0; /* Already there? - Use existing one! */
          else hr = E_OUTOFMEMORY;
        }
    }
  VariantClear(&var);
  return hr;
}

/******* ******* ******* ******* ******* ******* ******* *******/

int driver_init(int lflags)
{
  loDriver ld;
  VARIANT var;
  loTagId tti;
  int ecode;

  setlocale(LC_CTYPE, "");

  if (my_service) 
    {
      UL_ERROR((LOGID, "Driver already initialized!"));
      return 0;
    }

  memset(&ld, 0, sizeof(ld));   /* basic server parameters: */
//  ld.ldRefreshRate = 3;//10;
  ld.ldSubscribe = activation_monitor;
  ld.ldWriteTags = WriteTags;
//  ld.ldReadTags = ReadTags;
  ld.ldConvertTags = ConvertTags;
#if 0
  ld.ldAskItemID = AskItemID;
#endif
  ld.ldFlags = lflags | loDF_IGNCASE |  /*loDf_FREEMARSH | loDf_BOTHMODEL | */
    /*loDF_NOCOMP| */ loDf_NOFORCE & 0 /*| loDF_SUBSCRIBE_RAW*/;
    /*Fix the Bug in ProTool *//*|loDF_IGNCASE */ ;
  ld.ldBranchSep = '/'; /* Hierarchial branch separator */

  ecode = loServiceCreate(&my_service, &ld, 64 /* number of tags in the cache */);
                                               /* 500000 is ok too */ 
  UL_TRACE((LOGID, "%!e loCreate()=", ecode));
  if (ecode) return -1;

  InitializeCriticalSection(&lk_values);
  memset(tv, 0, sizeof(tv));    /* instead of VariantInit() for each of them */

  VariantInit(&var);

/* OPTIONAL: Tags creation. Do you need a few tags? */

  ecode = loAddRealTag_b(my_service,    /* actual service context */
                         &tti,  /* returned TagId */
                         0,     /* != 0  driver's key */
                         "Just the hint / [0...999]",   /* tag name (hint) */
                         0,     /* loTF_ Flags */
                         OPC_READABLE | OPC_WRITEABLE, 0);

  V_I1(&var) = -1; /* the good practice: set the value first, then type. */
  V_VT(&var) = VT_I1; /* Do you know why? */

  ecode = loAddRealTag_a(my_service,    
                  &ti[TI_bandwidth], /* returned TagId (lightopc's identifier)*/
                  (loRealTag)TI_bandwidth, /* != 0  (driver's internal identifier)*/
                  tn[TI_bandwidth],      /* tag name */
                  0,                     /* loTF_ Flags */
                  OPC_READABLE,          /* OPC access rights */
                  &var,                  /* type and value for conversion checks */
                  -1, 101); /*Analog EUtype: from -1 (unknown) to 101% (overload)*/
  /* Shows current bandwidth */

  /* We needn't to VariantClear() for simple datatypes like numbers */
  V_R8(&var) = 214.1; /* initial value. Will be used to check types conersions */
  V_VT(&var) = VT_R8;
  ecode = loAddRealTag_a(my_service,    /* actual service context */
                         &ti[TI_zuzu],  /* returned TagId */
                         (loRealTag)TI_zuzu, /* != 0 driver's key */
                         tn[TI_zuzu],   /* tag name */
                         0,     /* loTF_ Flags */
                         OPC_READABLE | OPC_WRITEABLE, &var, 12., 1200.);
  UL_TRACE((LOGID, "%!e loAddRealTag_a(zuzu) = %u ", ecode, ti[TI_zuzu]));

  V_I2(&var) = 1000;
  V_VT(&var) = VT_I2;
  ecode = loAddRealTag(my_service,      /* actual service context */
                       &ti[TI_lulu],    /* returned TagId */
                       (loRealTag) TI_lulu,     /* != 0 driver's key */
                       tn[TI_lulu],     /* tag name */
                       0,       /* loTF_ Flags */
                       OPC_READABLE | OPC_WRITEABLE, &var, 0, 0);
  UL_TRACE((LOGID, "%!e loAddRealTag(lulu) = %u ", ecode, ti[TI_lulu]));

  /* This 2nd 'zuzu' will fail with EEXISTS */
  ecode = loAddRealTag(my_service,     
                       &tti,    /* returned TagId */
                       (loRealTag) TI_zuzu,     /* != 0 driver's key */
                       "zuzu",  /* tag name */
                       0,       /* loTF_ Flags */
                       OPC_READABLE | OPC_WRITEABLE, &var, 0, 0);
  UL_TRACE((LOGID, "%!e loAddRealTag(zuzu) = %u (duplicated)", ecode, tti));

#if 1 /* OPTIONAL: generate several tags to test capabilites & performance */
  {
    char name[64];
    int ii, sep;
    DWORD sttime = GetTickCount();
    memset(name, 0, sizeof(name));
    strcpy(name, "A Huge list /");
    ii = strlen(name);
    memset(name + ii, 'Z', 32 - ii);

    for(ecode = 0, sep = '-'; *name <= 'B'; sep = '/', (*name)++)
      {
        for(ii = 0; ii < 4 /*0000 */ && !ecode; ii++)
          {
            loTagId tt;
            sprintf(name + 32, ".%010u%c@", ii, sep);
            ecode = loAddRealTag_b(my_service,
                                   &tt, 0, name, 0, OPC_READABLE,
                                   ti[TI_bandwidth]);
/* loAddRealTag_b() inherits attributes of specified tag - ti[TI_bandwidth] */
          }
        UL_WARNING((LOGID, "%u tags created for %d mS",
                    ii * (*name - 'A' + 1), GetTickCount() - sttime));
      }
  }
#endif

  loAddRealTag(my_service, &ti[TI_quiet], (loRealTag) TI_quiet, tn[TI_quiet],
               0, OPC_READABLE, &var, 0, 0);

  loAddRealTag(my_service, &tti, 0, "wr-only", 0, OPC_WRITEABLE, &var, 0, 0);

  /* OPTIONAL: Create some Hierachial structure: */
#define ADD_TAG(name) loAddRealTag_b(my_service, &tti, \
                      0, name, 0,\
                      OPC_READABLE|OPC_WRITEABLE, tti)
  ADD_TAG("Tree/qw/qq");
  ADD_TAG("Tree/qw/zz");
  ADD_TAG("Tree/qw/ii/hh");
  ADD_TAG("Tree/qw/ii/yy");
  ADD_TAG("Tree/qw/ii/yy/mm/dd");
  ADD_TAG("Tree/eec/ii/yy/mMm/dd");
  ADD_TAG("Tree/eec/ii/yy/mMm/ddd");
  ADD_TAG("Tree/ee/ii/yy/mm/dd");
  ADD_TAG("Tree/ee/ii/yyy/mm/dd");

/* OPTIONAL:  Advanced Item Properies: defining and assignement */
{                             
  loPLid plid;

  if (0 == (plid = loPropListCreate(my_service)))
    {
      UL_WARNING((LOGID, "loPropListCreate() FAILED"));
    }
  else
    {
      V_R8(&var) = 999.9;
      V_VT(&var) = VT_R8;
      if (loPropertyAdd(my_service, plid, 102, &var, 0, 0) ||
          loPropertyAdd(my_service, plid, 5001, 0, "/Two", 0) ||
          loPropertyAdd(my_service, plid, 5002, 0, "//Two", 0) ||
          loPropertyAdd(my_service, plid, 5003, 0, "Two",
                        "a Custom property Two"))
        {
          UL_WARNING((LOGID, "loPropertyAdd() FAILED"));
        }
      ADD_TAG("device/port/one/Two");
      loPropListAssign(my_service, plid, tti, 1);
      ADD_TAG("device/port/one");
      loPropListAssign(my_service, plid, tti, 1);
      ADD_TAG("device/port/Two");
      loPropListAssign(my_service, plid, tti, 1);
      ADD_TAG("device/port");
      loPropListAssign(my_service, plid, tti, 1);
      ADD_TAG("device/Two");
      loPropListAssign(my_service, plid, tti, 1);
      ADD_TAG("device");
      loPropListAssign(my_service, plid, tti, 1);
      ADD_TAG("Two");
      loPropListAssign(my_service, plid, tti, 1);
    }
}
#undef ADD_TAG
#if 1 /* OPTIONAL: Creation of complex datatypes */
{
  SAFEARRAY *sa;
  SAFEARRAYBOUND sbound[1];
  sbound[0].lLbound = 0;
  sbound[0].cElements = 2;

/*** VT_ARRAY type */
  VariantInit(&tv[TI_array].tvValue);

  if (sa = SafeArrayCreate(VT_I4, 1, sbound))
    {
      HRESULT hr;
      long ix0 = 0, ix1 = 1, val = 333;

      V_ARRAY(&tv[TI_array].tvValue) = sa;
      V_VT(&tv[TI_array].tvValue) = VT_ARRAY | VT_I4;

      if (S_OK != (hr = SafeArrayPutElement(sa, &ix0, &val)) ||
          S_OK != (hr = SafeArrayPutElement(sa, &ix1, &val)))
        {
          UL_NOTICE((LOGID, "%!l SafeArray", hr));
          VariantClear(&tv[TI_array].tvValue);
        }
      else
         if (!loAddRealTag(my_service, &ti[TI_array], 
                    (loRealTag)TI_array, tn[TI_array],
                    loTF_CONVERT, OPC_READABLE | OPC_WRITEABLE,
                    &tv[TI_array].tvValue, 0, 0))
        {
          tv[TI_array].tvTi = ti[TI_array];
          tv[TI_array].tvState.tsError = S_OK;
          tv[TI_array].tvState.tsQuality = OPC_QUALITY_GOOD;
        }
    }
  else
    {
      UL_ERROR((LOGID, "driver_init(): SafeArrayCreate() failed"));
    }

/*** An enumerated type (localized weekdays names) with EUinfo ***/
  sbound[0].lLbound = 0;
  sbound[0].cElements = 7;

  VariantInit(&tv[TI_enum].tvValue);
  V_I2(&tv[TI_enum].tvValue) = 6;
  V_VT(&tv[TI_enum].tvValue) = VT_I2;

  if (sa = SafeArrayCreate(VT_BSTR, 1, sbound))
    {
      VARIANT ed;
      VariantInit(&ed);
      long ix;

      V_VT(&ed) = VT_ARRAY | VT_BSTR;
      V_ARRAY(&ed) = sa;

      for(ix = 0; ix < 7; ix++)
        {
          HRESULT hr;
          BSTR bs;
          WCHAR ws[32];
          local_text(ws, (unsigned)ix, 0); /* generates localized name */

          bs = SysAllocString(ws);
          if (S_OK != (hr = SafeArrayPutElement(sa, &ix, bs)))
            {
              UL_NOTICE((LOGID, "%!l SafeArray PutString", hr));
            }
          SysFreeString(bs);
        }

      if (!loAddRealTag(my_service, &ti[TI_enum], (loRealTag) TI_enum,
                        tn[TI_enum], loTF_CONVERT/*localization request*/, 
                        OPC_READABLE, &tv[TI_enum].tvValue, OPC_ENUMERATED, &ed))
        {
          tv[TI_enum].tvTi = ti[TI_enum];
          tv[TI_enum].tvState.tsError = S_OK;
          tv[TI_enum].tvState.tsQuality = OPC_QUALITY_GOOD;
        }
      VariantClear(&ed);
    }
  else
    {
      UL_ERROR((LOGID, "driver_init(): SafeArrayCreate(enum) failed"));
    }
}
#endif

/*** Show differnt OPC-Qualities ***/
  V_BSTR(&tv[TI_quality].tvValue) = SysAllocString(L"");
  V_VT(&tv[TI_quality].tvValue) = VT_BSTR;
  ecode = loAddRealTag(my_service, &ti[TI_quality],
                       (loRealTag) TI_quality, tn[TI_quality],
                       0, OPC_READABLE | OPC_WRITEABLE, 
                       &tv[TI_quality].tvValue, 0, 0);

/*** STRING (VT_BSTR) datatype  ***/
  V_BSTR(&tv[TI_string].tvValue) = SysAllocString(L"");
  V_VT(&tv[TI_string].tvValue) = VT_BSTR;
  ecode = loAddRealTag(my_service, &ti[TI_string],  
                       (loRealTag) TI_string, tn[TI_string],     
                       0, OPC_READABLE | OPC_WRITEABLE, 
                       &tv[TI_string].tvValue, 0, 0);
//  VariantClear(&var); 
  /* don't required because we didn't assigned complex types to var */

  return 0;
}

void driver_destroy(void)
{
  if (my_service)
    {
      int ecode = loServiceDestroy(my_service);
      UL_INFO((LOGID, "%!e loDelete(%p) = ", ecode));

      for(ecode = 0; ecode < sizeof(tv) / sizeof(tv[0]); ecode++)
        VariantClear(&tv[ecode].tvValue);

      DeleteCriticalSection(&lk_values);

      my_service = 0;
    }
}

/********* Data simulator stuff ************************************************/

void simulate(unsigned pause)
{
  DWORD hitime = 0;
  unsigned starttime = GetTickCount();
  UL_WARNING((LOGID, "Simulator Started..."));

  EnterCriticalSection(&lk_values);

/* Set up initial values for the tags we didn't initialized in driver_init(): */

  tv[TI_zuzu].tvTi = ti[TI_zuzu];
  tv[TI_zuzu].tvState.tsError = S_OK;
  tv[TI_zuzu].tvState.tsQuality = OPC_QUALITY_GOOD;
  V_VT(&tv[TI_zuzu].tvValue) = VT_R8;
  V_R8(&tv[TI_zuzu].tvValue) = -100;

  tv[TI_lulu].tvTi = ti[TI_lulu];
  tv[TI_lulu].tvState.tsError = S_OK;
  tv[TI_lulu].tvState.tsQuality = OPC_QUALITY_GOOD;
  V_VT(&tv[TI_lulu].tvValue) = VT_I2;
  V_I2(&tv[TI_lulu].tvValue) = 78;

  tv[TI_enum].tvTi = ti[TI_enum];
  tv[TI_enum].tvState.tsError = S_OK;
  tv[TI_enum].tvState.tsQuality = OPC_QUALITY_GOOD;
  V_VT(&tv[TI_enum].tvValue) = VT_I2;
  V_I2(&tv[TI_enum].tvValue) = 1;

  tv[TI_bandwidth].tvTi = ti[TI_bandwidth];
  tv[TI_bandwidth].tvState.tsError = S_OK;
  tv[TI_bandwidth].tvState.tsQuality = OPC_QUALITY_GOOD;
  V_VT(&tv[TI_bandwidth].tvValue) = VT_I1;
  V_I1(&tv[TI_bandwidth].tvValue) = -1;

  tv[TI_quiet].tvTi = ti[TI_quiet];
  tv[TI_quiet].tvState.tsError = S_OK;
  tv[TI_quiet].tvState.tsQuality = OPC_QUALITY_LAST_KNOWN;
  V_VT(&tv[TI_quiet].tvValue) = VT_I2;
  V_I2(&tv[TI_quiet].tvValue) = 1412;

  tv[TI_quality].tvTi = ti[TI_quality];
  tv[TI_quality].tvState.tsError = S_OK;
//  tv[TI_quality].tvValue -- already assigned

  tv[TI_string].tvTi = ti[TI_string];
  tv[TI_string].tvState.tsQuality = OPC_QUALITY_GOOD;
  tv[TI_string].tvState.tsError = S_OK;
//  tv[TI_string].tvValue -- already assigned

//  tv[TI_enum], tv[TI_array], string, quality, -- already assigned 

  LeaveCriticalSection(&lk_values);

/**** Then do simulate ***********/

  while(0 != my_CF.server_inuse) /* still working? */
    {
      FILETIME ft;

      Sleep(10);   /* main delay */
      GetSystemTimeAsFileTime(&ft); /* awoke */

/* OPTIONAL: reload log's configuration fromtime to time */
      if (hitime != (ft.dwLowDateTime & 0xf8000000))    /* 13.5 sec */
        {                       /* 0xff000000 is about 1.67 sec */
          hitime = ft.dwLowDateTime & 0xf8000000;
#if 0
          unilog_Refresh(0);    /* all logs */
#else
          unilog_Refresh("LightOPC");
          unilog_Refresh("Lopc-Sample-exe");
          unilog_Refresh("Lopc-Sample-dll");
#endif
        }

/***** The main job: update the values ******/
      EnterCriticalSection(&lk_values);

double zuzu = 
      (V_R8(&tv[TI_zuzu].tvValue) += 1./3.); /* main simulation */
      V_VT(&tv[TI_zuzu].tvValue) = VT_R8;
      tv[TI_zuzu].tvState.tsTime = ft;

      V_I2(&tv[TI_lulu].tvValue) = (short)zuzu;
      V_VT(&tv[TI_lulu].tvValue) = VT_I2;
      tv[TI_lulu].tvState.tsTime = ft;

      V_I2(&tv[TI_enum].tvValue) = (short)((ft.dwLowDateTime >> 22) % 7);
      V_VT(&tv[TI_enum].tvValue) = VT_I2;
      tv[TI_enum].tvState.tsTime = ft;

      V_I1(&tv[TI_bandwidth].tvValue) = (char)loGetBandwidth(my_service, 0);
      V_VT(&tv[TI_bandwidth].tvValue) = VT_I1;
      tv[TI_bandwidth].tvState.tsTime = ft;
      
/** OPTIONAL: enumerate all possible qualities: */

⌨️ 快捷键说明

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