НЕТ.
ldReadTags() вызывается только по запросам чтения OPC_DS_DEVICE. Обычно OPC клиенты используют только чтение из кеша OPC_DS_CACHE.
Чтение из кеша полностю обрабатывается внутри LightOPC, поэтому драйвер должен регулярно обновлять кеш сервера через loCacheXXXXX(). Фактически, даже внутри ldReadTags(), выполнив реальное чтение, драйвер должен явно обновить кеш через loCacheXXXXX().
Таким образом, определять ldReadTags() не обязательно. Эта функция может понадобиться для реализации чтения с побочными эффектами, а также позволяет гарантирует атомарность и очередность запросов к устройству, если это необходимо.
Никак, вероятно. Желательно инициализировать ldRefreshRate в соответствии с производительностью вышей системы и требованиями ваших устройств. Разумный диапазон - 30...1000 мс. LightOPC вполне самостоятельно разбирается со всеми обновлениями для клиентов.
Ваш драйвер должен поддерживать кеш актуальным и не обращать внимания на UpdateRate, запрашиваемые глупыми клиентами.
Обычно требуетя чтобы сервер гарантировал определенную частоту опроса устройств, независящую от количества подключенных клиентов и заказанных ими частот обновления.
Драйвер может опрашивать устройства (и обновлять кеш) с такой частотой, которая удовлетворяет вас, ваш компутер, ваши устройсва и процессы, контролируемые этими устройствами. Функция loCacheUpdate() специально сделана достаточо быстрой для использования в критичноых ко времени циклах. Она не создает непредсказуемых задержек, поскольку не блокируется на неопределенное время. Если лишний VariantCopy() кажется вам расточительством - попробуйте loCacheLock() / loCacheUnlock().
Таким образом, частота обновлений / обращений к устройству определяется исключительно драйвером. Это позволяет драйверу правильно распределять доступную полосу пропускания между устройствами.
Есть две лазейки для снижения частоты опроса устройств:
Вычисляя timestamp для тегов, ведомых прерываниями, необходимо учитывать реальную задержку реакции на прерывание.
Вероятно, вы используете код
loServiceCreate(&my_service, &ld, XXX);
Где XXX устанавливает максимальное количество обслуживаемых тегов.
Просто увеличте это число.
Установленный предел не может быть изменен без пересоздания loService по соображениям производительности.
Однажды созданный тег не может быть унчтожен. Поэтому в общем случае для изменения адресного пространства сервер необходимо перезапустить. Однако...
Обычно, динамическое изменение адресного пространства сервера приносит больше вреда, чем пользы:
Определите процедуру ldAskItemId() для отображения порожденных имен на безымянные теги.
Создайте тег "подсказку" (hint) с желаемым именем (например, "Reg[0...32727]") и пустым (NULL или VT_EMPTY) tdValue или установленным loTF_EMPTY. Этот псевдотег будет виден только через BrowseAddresSpace.
Создайте необходимое количество безымянных тегов (tdName = NULL или "").
loRealTag определяется драйвером, а LightOPC включается его в запросы к драйверу (loTagPair::tpRt). Если драйвер имеет некоторые данные, ассоциируемые с тегом, то указатель на эти данные имеет смысл сохранить как RealTag. Можно даже определить struct loRealTag_ по вашему усмотрению. Тогда при обработке запросов вам не придется выполнять поиск тега по TagId.
Следует различать интерфейс IOPCSecurity и OPC Security вообще. LightOPC позволяет реализовать многие механизмы защиты.
Интерфейс IOPCSecurity не реализован непосредственно, поскольку он не предоставляет сколь-нибудь полезных нетривиальных услуг. Однако, он может быть реализован и включен в loClient через loClientChain().
Любая "защита" строится из аутентификации и авторизации. IOPCSecurity не предусматривает авторизацию (т.е. не сопоставлят права доступа и пользователей).
В простейшем случае вы можете поделить ваши теги на несколько групп и обслуживать их разными серверами с разной DCOM авторизацией. Эти серверы могут исполняться в одном процессе.
Чтобы ввести в ваш сервер защиту на уровне отдельных тегов необходимо:
Ох... Сам по себе LightOPC "свободен" аки птиц.
Для exe-серверов существенна инициализация нитки, обслуживающей фабрику классов. IMHO, COINIT_MULTITHREADED предпочтительней. Использовать COINIT_APARTMENTTHREADED тоже можно, но такая нитка должна обрабатывать оконные сообщения. Кроме того, полезно в loDriver::ldFlags установить флаги (loDf_BOTHMODEL | loDf_FREEMARSH) вместо loDf_FREEMODEL.
Для того, чтобы показывать приличную производительность в комбинации
in-proc сервера с однониточным клиентом имеется поддержка модели both.
Эта модель должна быть разрешена при компиляции (LO_USE_BOTHMODEL и LO_USE_FREEMARSHALL)
и при исполнении (loDf_BOTHMODEL и loDf_FREEMARSH). Поскольку both
модель тормозит многониточных клиентов ее поддержку можно включать для
отдельных клиентов.
loDf_BOTHMODEL приводит к использованию локальных message loop в процедурах синхронизации ниток, что в общем случае плохо сказывается на надежности сервера.
Вы действительно недовольны бенчмарками?
Мы не являемся членом OPC Foundation и, вероятно, никогда им не станем. Поэтому ни Automation Wrapper DLL, ни тестов соответствия у нас нет.
Скомпилированный opcXXXauto.dll имеется в демонстрационных пакетах многих производителей. В частности, Matrikon Explorer & Simulator, KEPware, etc.
LightOPC прекрасно работает с такими Automation конвертерами.
Нет.
IMHO, OPC описывает именно клиентский API и писать клиентов на чистом OPC
достаточно просто. Дальнейшее упрощение интерфейса приведет только к
сокращению функциональности.
Посмотите следующие ссылки:
Перед вызовом loServiceCreate() установите
loDriver::ldRefreshRate равным 1 или иному значению,
дольному 1000 мс.
Подробности о ldRefreshRate см. в lightopc.h и
руководстве.
ftp://ftp.ipi.ac.ru/pub/LightOPC/ unilog-current.tgz
Пишите: master AT ipi ac ru