Как работать с OPC
От: Андрей А. Тельнов  
Дата: 15.03.02 04:48
Оценка:
Подскажите ссылку на (желательно русскоязычную) страничку, которая может оказать помощь при написании OPC клиентов.
Re: Как работать с OPC
От: Cory Россия  
Дата: 15.03.02 06:54
Оценка:
Здравствуйте Андрей А. Тельнов, Вы писали:

ААТ>Подскажите ссылку на (желательно русскоязычную) страничку, которая может оказать помощь при написании OPC клиентов.


Ссылок не дам, но могу кинуть спецификацию OPC и примеры кода (на VС++,VB). Только почту подскажи, и я пришлю.
Мой адрес:
Re[2]: Как работать с OPC
От: Андрей А. Тельнов  
Дата: 19.03.02 04:45
Оценка:
Здравствуйте Cory, Вы писали:

C>Ссылок не дам, но могу кинуть спецификацию OPC и примеры кода (на VС++,VB). Только почту подскажи, и я пришлю.


Сбросить письмо на Ваш email не удалось, поэтому пишу здесь
atelnov@pisem.net
Re[2]: Как работать с OPC
От: geagle  
Дата: 22.02.03 13:32
Оценка:
Здравствуйте, Cory, Вы писали:

C>Здравствуйте Андрей А. Тельнов, Вы писали:


ААТ>>Подскажите ссылку на (желательно русскоязычную) страничку, которая может оказать помощь при написании OPC клиентов.


C>Ссылок не дам, но могу кинуть спецификацию OPC и примеры кода (на VС++,VB). Только почту подскажи, и я пришлю.

C>Мой адрес:
C>

Не мог бы и мне кинуть на geagle@yandex.ru
Re: Как работать с OPC
От: WolfHound  
Дата: 22.02.03 16:53
Оценка:
Здравствуйте, Андрей А. Тельнов, Вы писали:

ААТ>Подскажите ссылку на (желательно русскоязычную) страничку, которая может оказать помощь при написании OPC клиентов.

Везет некоторым...клиентов пишут, а я с серваком мучаюсь
... << RSDN@Home 1.0 beta 5 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[2]: Как работать с OPC
От: geagle  
Дата: 23.02.03 11:02
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, Андрей А. Тельнов, Вы писали:


ААТ>>Подскажите ссылку на (желательно русскоязычную) страничку, которая может оказать помощь при написании OPC клиентов.

WH>Везет некоторым...клиентов пишут, а я с серваком мучаюсь

WH>


С серваком Я еще успею намучаться. А пока мне надо написать клиента OPC. Я буду признателен за любую информацию на эту тему.
geagle@yandex.ru
Re[3]: Как работать с OPC
От: epflorov Россия www.epflorov.hotbox.ru
Дата: 23.02.03 12:14
Оценка:
Здравствуйте, geagle, Вы писали:
G> ...
G>С серваком Я еще успею намучаться. А пока мне надо написать клиента OPC. Я буду признателен за любую информацию на эту тему.
http://www.ipi.ac.ru/lab43/lopc-ru.html

Работает, проверено. Удачи!
Евгений Флоров
Re[4]: Как работать с OPC
От: geagle  
Дата: 23.02.03 20:33
Оценка:
Здравствуйте, epflorov, Вы писали:

E>Здравствуйте, geagle, Вы писали:

G>> ...
G>>С серваком Я еще успею намучаться. А пока мне надо написать клиента OPC. Я буду признателен за любую информацию на эту тему.
E>http://www.ipi.ac.ru/lab43/lopc-ru.html

E>Работает, проверено. Удачи!



Спасибо!
Re[5]: Как работать с OPC
От: WolfHound  
Дата: 23.02.03 21:12
Оценка:
Здравствуйте, geagle, Вы писали:

G>Спасибо!

Я так не думаю
Pass:        1864
Fail:        267
Warning:    22
Incomplete:    51

Ко всему тому код весьма уродливый, запутаный...
Вывод: Я бы не стал это использовать.

Чтобы не быть голословным привожу пример кода

Их
STDMETHODIMP LightOPCGroup::AddItems(DWORD dwCount,
                                     OPCITEMDEF *pItemArray,
                                     OPCITEMRESULT **ppAddResults,
                                     HRESULT **ppErrors)
{
 HRESULT hr;
 HRESULT *err = 0;
 OPCITEMRESULT *ir = 0;
 loTagId *tid = 0;
 void **acpath;
 LightOPCItem **oi = 0;
 DWORD ii;
 loService *se;
 loTagEntry *tags;
 unsigned act_count;
 loAA_DECLARE(sizeof(LightOPCItem*) + sizeof(loTagId) + sizeof(void*));

 LO_CHECK_STATEz2("AddItems", ppAddResults, ppErrors);
 if (!ppAddResults) { hr = E_INVALIDARG; goto Return; }

 ii = dwCount * (sizeof(*oi) + sizeof(*tid) + sizeof(*acpath));
 if (0 == ii) { hr = E_INVALIDARG; goto Return; }
 if (!(oi = (LightOPCItem**)loAA_ALLOC(ii))) { hr = E_OUTOFMEMORY; goto Return; }
 memset(oi, 0, ii);
 tid = (loTagId*)&oi[dwCount];
 acpath = (void**)&tid[dwCount];

 hr = internalValidateItems(dwCount, pItemArray, tid, acpath, &ir, &err);
 if (FAILED(hr)) goto Return;

 se = owner->se; tags = se->tags;

 for(ii = 0; ii < dwCount; ii++)
   if (S_OK == err[ii])
     {
      LightOPCItem *newby;
      hr = E_OUTOFMEMORY;

      if (oi[ii] = newby = new LightOPCItem)
        {
         OPCITEMDEF *idef = &pItemArray[ii];
         loTagAttrib *ta = &tags[tid[ii]].attr;
         newby->tid = tid[ii];
         newby->AcPath = acpath[ii];
         newby->hClient = idef->hClient;

         newby->vtRequestedDataType = idef->vtRequestedDataType;
         newby->convtype = lo_check_conversion(ta, newby->vtRequestedDataType);

         hr = S_OK;
         if ((NULL == newby->AcPath ||
             S_OK == (hr = newby->set_accpath(idef->szAccessPath))) &&
             (!ta->taName || !(ta->taFlags & loTF_CANONAME) &&
#if 0
              wcscmp
#else
         se->wstrcmp
#endif
                    (ta->taName, idef->szItemID)))
           hr = newby->set_itemid(idef->szItemID);
         newby->Quality = -1;
         if (0 == (newby->bActive = 0 != idef->bActive))
           tid[ii] = 0, newby->Quality = OPC_QUALITY_OUT_OF_SERVICE;
//         else if (!(OPC_READABLE & tags[tid[ii]].attr.flag))
  //         newby->bActive = 0;
        }
      err[ii] = hr;
     }

 act_count = 0;
 lock_write();
    for(ii = 0; ii < dwCount; ii++)
      if (S_OK == err[ii])
        {
         unsigned idx;
         if (idx = add(oi[ii]))
           {
            act_count += oi[ii]->bActive /* != 0*/;
            oi[ii] = 0;
            ir[ii].hServer = (OPCHANDLE)idx;
           }
         else
           {
            err[ii] = E_OUTOFMEMORY;
            tid[ii] = 0;
            hr = S_FALSE;
           }
        }
      else
        {
         tid[ii] = 0;
         hr = S_FALSE;
        } /* end of for(;;) */
    if (act_count)
      {
       active_count += act_count;
       if (Active)
         {
          loChangeActivity(se, 1, (unsigned)dwCount, tid);
          last_trid = 0; /* force callback */
         }
      }
 unlock();

#if ll_NOTICE <= USE_LOG
    for(ii = 0; ii < dwCount; ii++)
      {
       if (S_OK == err[ii])
         UL_NOTICE((LOG_GR("AddItem(%ls)%08X(%ls) = %u/%u"),
                          loWnul(pItemArray[ii].szItemID),
                          pItemArray[ii].hClient,
                   loWnul(pItemArray[ii].szAccessPath),
              tid[ii], ir[ii].hServer));
       else
         UL_INFO((LOG_GR("AddItem(%ls)(%ls)%x/%x = %s"),
                       loWnul(pItemArray[ii].szItemID),
                  loWnul(pItemArray[ii].szAccessPath),
                           pItemArray[ii].vtRequestedDataType,
                           ir? ir[ii].vtCanonicalDataType: 0,
               loStrError(err[ii])));
      }
#endif


Return:

 if (oi)
   {
    for(ii = 0; ii < dwCount; ii++)
      if (oi[ii]) delete oi[ii];
    loAA_FREE(oi);
   }

 if (FAILED(hr))
   {
    UL_INFO((LOG_GRH("AddItems(%lu) = %s"), dwCount, loStrError(hr)));
   }
 else
   {
    *ppAddResults = ir, ir = 0;
    if (ppErrors) *ppErrors = err, err = 0;
    UL_NOTICE((LOG_GRH("AddItems(%lu) = %s"), dwCount, loStrError(hr)));
   }
 if (ir)  loComFree(ir);
 if (err) loComFree(err);

 LO_FINISH();
 return hr;
}


Мой(дома нет последней версии там все еще красивей)
STDMETHODIMP CSRCOMMOPCGroup::AddItems( 
/* [in] */                        DWORD dwCount,
/* [size_is][in] */                OPCITEMDEF *pItemArray,
/* [size_is][size_is][out] */    OPCITEMRESULT **ppAddResults,
/* [size_is][size_is][out] */    HRESULT **ppErrors
)
{
    LogPrint(L"IOPCItemMgt::AddItems\n");
    if(m_Public)        return OPC_E_PUBLIC;
    if(dwCount<=0)        return E_INVALIDARG;
    if(!pItemArray)        return E_POINTER;
    if(!ppAddResults)    return E_POINTER;    *ppAddResults=0;
    if(!ppErrors)        return E_POINTER;    *ppErrors=0;
    T_CoAutoArr<HRESULT>        hr(dwCount);
    T_CoAutoArr<OPCITEMRESULT>    ir(dwCount);
    if(!hr||!ir)return E_OUTOFMEMORY;
    UINT fails=0;
    {//Sync
        C_SyncHelper lockDItem(g_DItemSync, C_SyncHelper::Read);
        C_SyncHelper lockThis(this, C_SyncHelper::Write);
        for(UINT i=0;i<dwCount;i++)
        {
            T_CoPtr<COPCGroupItem> p=new COPCGroupItem(this);
            int h=m_Items.Include(p);
            hr[i]=p->Init(&pItemArray[i], &ir[i], h);
            if(FAILED(hr[i]))
            {
                fails++;
                m_Items.Exclude(h);
                ir[i].dwAccessRights        =0;
                ir[i].dwBlobSize            =0;
                ir[i].hServer                =g_ItemIndex.end();
                ir[i].pBlob                    =0;
                ir[i].vtCanonicalDataType    =VT_ERROR;
                ir[i].wReserved                =0;
            }
        }
    }
    *ppAddResults    =ir.Detach();
    *ppErrors        =hr.Detach();
    if(fails)    return S_FALSE;
    else        return S_OK;
}

HRESULT COPCGroupItem::Init(OPCITEMDEF* def, OPCITEMRESULT* res, int sHandle)
{
    m_AccessPath        =def->szAccessPath;
    m_ItemID            =def->szItemID;

    m_vtRequested        =def->vtRequestedDataType;
    m_Active            =def->bActive;

    WCHAR* path =def->szItemID;
    int cur=GetDHandleByName(m_ItemID);
    if(!g_ItemIndex.Check(cur))return OPC_E_INVALIDITEMID;
     m_hDeviceItem        =cur;
    m_hServerItem        =sHandle;
    m_hClientItem        =def->hClient;

    if(res)
    {
        COPCDeviceItem*    DItem=g_ItemIndex[m_hDeviceItem];

        res->hServer                =m_hServerItem;
        res->vtCanonicalDataType    =DItem->GetType();
        res->dwAccessRights            =DItem->GetAccess();
        res->pBlob                    =0;
        res->dwBlobSize                =0;
        res->wReserved                =0;
    }
    return S_OK;
}
... << RSDN@Home 1.0 beta 5 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[6]: Как работать с OPC
От: WolfHound  
Дата: 23.02.03 21:27
Оценка:
Здравствуйте, WolfHound, Вы писали:

В дагонку: у них память течет и сервак под нагрузкой валится.

ЗЫ Ну и кому после этого нужен их якобы крутой перформанс?
... << RSDN@Home 1.0 beta 5 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[6]: Как работать с OPC
От: geagle  
Дата: 24.02.03 07:29
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, geagle, Вы писали:


G>>Спасибо!

WH>Я так не думаю
WH>
WH>Pass:        1864
WH>Fail:        267
WH>Warning:    22
WH>Incomplete:    51
WH>

WH>Ко всему тому код весьма уродливый, запутаный...
WH>Вывод: Я бы не стал это использовать.

WH>Чтобы не быть голословным привожу пример кода




Спасибо за предупреждение.
Не могли бы Вы мне предоставить более подробную информацию на эту тему.
Re[6]: Как работать с OPC
От: epflorov Россия www.epflorov.hotbox.ru
Дата: 24.02.03 08:17
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH> ...

WH>Ко всему тому код весьма уродливый, запутаный...
WH>Вывод: Я бы не стал это использовать.

WH>Чтобы не быть голословным привожу пример кода

WH>Их
WH> ...
WH>Мой(дома нет последней версии там все еще красивей)
WH> ...
А что значит "мой", у вас есть своя подобная библиотека? Где-то можно взглянуть? (в смысле насколько она свободна)
Евгений Флоров
Re[7]: Как работать с OPC
От: epflorov Россия www.epflorov.hotbox.ru
Дата: 24.02.03 08:24
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, WolfHound, Вы писали:


WH>В дагонку: у них память течет и сервак под нагрузкой валится.

Какова должна быть нагрузка, чтобы он упал?

WH>ЗЫ Ну и кому после этого нужен их якобы крутой перформанс?


Я обратил внимание на эту библиотеку из-за простоты использования. И это пожалуй наверное единственная общедоступная бесплатная библиотека. Так к ней и надо относиться.
Если есть достойные альтернативы, сообщите пожалуйста. Я думаю это будет интересно всем!
Евгений Флоров
Re[8]: Как работать с OPC
От: WolfHound  
Дата: 24.02.03 09:56
Оценка:
Здравствуйте, epflorov, Вы писали:

WH>>В дагонку: у них память течет и сервак под нагрузкой валится.

E>Какова должна быть нагрузка, чтобы он упал?
Прогнал стресс тест 2 с половиной раза у него утекло примерно 2М памяти после чего он рухнул. В реальных условиях будет рухать как минимум раз в день.

E>Я обратил внимание на эту библиотеку из-за простоты использования. И это пожалуй наверное единственная общедоступная бесплатная библиотека. Так к ней и надо относиться.

E>Если есть достойные альтернативы, сообщите пожалуйста. Я думаю это будет интересно всем!
Я не видел ни одной приличной библиотеки ни бесплатной ни комерческой... По сему было принято решение писать с нуля что я собственно и сделал.
... << RSDN@Home 1.0 beta 5 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[7]: Как работать с OPC
От: WolfHound  
Дата: 24.02.03 09:56
Оценка:
Здравствуйте, epflorov, Вы писали:

E>А что значит "мой", у вас есть своя подобная библиотека? Где-то можно взглянуть? (в смысле насколько она свободна)

"Мой" в смысле мной написаный но принадлежит он конторе посему без раздрешения начальства я его публиковать не имею права.
... << RSDN@Home 1.0 beta 5 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[7]: Как работать с OPC
От: WolfHound  
Дата: 24.02.03 09:56
Оценка:
Здравствуйте, geagle, Вы писали:

G>Спасибо за предупреждение.

Назачто.

G>Не могли бы Вы мне предоставить более подробную информацию на эту тему.

Какую?
... << RSDN@Home 1.0 beta 5 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[8]: Как работать с OPC
От: geagle  
Дата: 24.02.03 16:03
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, geagle, Вы писали:


G>>Спасибо за предупреждение.

WH>Назачто.

G>>Не могли бы Вы мне предоставить более подробную информацию на эту тему.

WH>Какую?

WH>

Мне нужно разработать клиента для чужого OPC сервера.
Буду, благодарен за любую информацию на эту тему.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.