EnglishУкраїнськаmRussian
Login/New
Topic with many replies

Пересылка событийной информации между Scada-станциями


Author Message
Written on: 27. 05. 2012 [11:12]
DJ-AMIGO
Михаил Гончаров
Topic creator
registered since: 26.05.2012
Posts: 15
Добрый день, Эксперты!
Имеется задача: оснащение множества географически распределенных удаленных торговых точек системой сбора информации о различных ключевых событиях, составляющих формально описанный бизнес-процесс.
Разумеется сюда входят такие модули, как детальный мониторинг посещаемости, информации о привлечении внимания к той или иной витрине, сбор информации с терминалов голосования (для статистического оценивания удовлетворенности покупателей качеством обслуживания), подсистема аудита расчетно-кассовых операций, подсистема мониторинга безопасности объекта и прочие подсистемы.
При этом тестовый сервер опроса (на базе ПЛК ICP DAS 5441) уже сконфигурирован на базе OpenSCADA (если честно, меня поразила глубина замысла и стройность архитектуры этой системы). Такие контроллеры планируется в дальнейшем устанавливать на удаленных объектах (в торговых точках).
Ключевым моментом является возможность передачи сообщений из удаленной SCADA-станции на центральный SCADA-сервер. Для этого в центральном филиале планируется поднять SCADA-сервер с ролью архиватора сообщений. Связь между центральным сервером и удаленными ПЛК будет осуществляться через Интернет-канал одним из доступных в OpenSCADA способом (например SSL). Причем инициатором сеанса пересылки сообщения должен быть удаленный узел (источник сообщения). Пересылка сообщений должна происходить периодически с заданным периодом (например 5-10 мин.), при этом соединение с центральным сервером устанавливается только на время пересылки, затем оно разрывается до следующего сеанса связи. Если во время очередного сеанса пересылка сообщения не удалась, то оно буферизуется в очереди сообщений (архиве сообщений) подсистемы архивов OpenSCADA. Затем при удачной попытке связи с центром все накопленные сообщения должны постепенно сбрасываться на центральный узел. Собственно структура системы такая.
В принципе структура объекта-сообщения в OpenSCADA вполне позволяет его сделать типизированным (например вложив XML-посылку).
Сможете ли вы направить мои действия в нужное русло?
Интересует прежде всего механизм пересылки сообщений между SCADA-станциями по инициативе отправителя.
Written on: 27. 05. 2012 [20:24]
roman
Roman Savochenko
Moderator
Contributor
Developer
registered since: 12.12.2007
Posts: 3750
"DJ-AMIGO" wrote:

Ключевым моментом является возможность передачи сообщений из удаленной SCADA-станции на центральный SCADA-сервер. Для этого в центральном филиале планируется поднять SCADA-сервер с ролью архиватора сообщений. Связь между центральным сервером и удаленными ПЛК будет осуществляться через Интернет-канал одним из доступных в OpenSCADA способом (например SSL). Причем инициатором сеанса пересылки сообщения должен быть удаленный узел (источник сообщения).

GPRS наверное.

"DJ-AMIGO" wrote:

Пересылка сообщений должна происходить периодически с заданным периодом (например 5-10 мин.), при этом соединение с центральным сервером устанавливается только на время пересылки, затем оно разрывается до следующего сеанса связи.

Для GPRS 5-10 мин нормально, поскольку подключение от 1 до 10 секунд. Хотя смысла особого подключать, а затем отключать нет поскольку оплата всёравно за трафик.

"DJ-AMIGO" wrote:

Если во время очередного сеанса пересылка сообщения не удалась, то оно буферизуется в очереди сообщений (архиве сообщений) подсистемы архивов OpenSCADA. Затем при удачной попытке связи с центром все накопленные сообщения должны постепенно сбрасываться на центральный узел. Собственно структура системы такая.

Если поток сообщений не сильно велик то на клиенте достаточно просто буфера сообщений хотя нет никаких проблем держать их на некоторую глубину в локальном архиве, а для сброса на сервер достаточно держать метку времени последнего удачного сброса.

"DJ-AMIGO" wrote:

В принципе структура объекта-сообщения в OpenSCADA вполне позволяет его сделать типизированным (например вложив XML-посылку).
Сможете ли вы направить мои действия в нужное русло?
Интересует прежде всего механизм пересылки сообщений между SCADA-станциями по инициативе отправителя.

Создаёте процедуру в JavaLikeCalc контроллере, на клиенте, которая будет читать последние сообщения и отправлять их на центральный сервер, возможно с вызовом системного скрипта подключения, а затем отключения связи.

Однако, если сервисная функция интерфейса управления для запроса сообщений присутствует, то функции записи нет.
Сегодня добавлю.

Learn, learn and learn better than work, work and work.
Written on: 28. 05. 2012 [15:11]
DJ-AMIGO
Михаил Гончаров
Topic creator
registered since: 26.05.2012
Posts: 15
Однако, если сервисная функция интерфейса управления для запроса сообщений присутствует, то функции записи нет.

Роман, под сервисной функцией интерфейса управления для запроса сообщений понимается: <get path="/sub_Archive/%2fserv%2fmess"/>
Но что Вы имели ввиду под функцией записи? (аналогичная сервисная функция, записывающая сообщение в буфер сообщений?)

Мой поиск и изучение API-OpenSCADA привел меня к следующему:
1. Механизм коммуникации между двумя SCADA-станциями можно попробовать осуществить через встроенный интерфейс управления системой. Среди публичных методов имеется
void cntrCmd( XMLNode *opt, int lev = 0, const string &path = "", int off = 0 ); — Команда работы с интерфейсом управления системы.
С помощью этого метода возможна пересылка заранее заготовленных XML-посылок? Формат структуры в XML должен подчиняться каким-нибудь стандартам? Или здесь все зависит от фантазии программиста.
Имеется ли возможность объект-сообщения TMess перевести в XML-формат, а затем десериализовать обратно в объект?
Для работы этого интерфейса управления системой с удаленной SCADA-станцией нужно ли создавать какие-то дополнительные объекты в проекте OpenSACADA, например протокол или транспорт? Или все конфигурационные параметры для соединения с удаленным сервером можно указать в JavaLikeCalc-пользовательском скрипте?
2. Очередь сообщений:
Для функционала очереди сообщений имеется Объект подсистемы «Архивы» TArchiveS, который имеет следующие функции:
void messPut( time_t tm, int utm, const string &categ, int8_t level, const string &mess ); — Помещение значения <mess> с уровнем <level> категории <categ> и время <tm>+<utm> в буфер, а затем в архив сообщений.
void messGet( time_t b_tm, time_t e_tm, vector<TMess::SRec> & recs, const string &category = "", int8_t level = TMess::Debug, const string &arch = "", time_t upTo = 0 ); — Запрос значений <reqs> за указанный период времени <b_tm>, <e_tm> для указанной категории (по шаблону) <category> и уровня <level> из архиватора <arch>.
Эти функции-методы, я так понимаю, работают с буфером сообщений и при необходимости прозрачно для вызывающего пользовательского кода могут перемещать их в архив сообщений подсистемы "Архивы" (или это происходит только по инициативе одного из экземпляров TMArchivator?).
Это очень полезная возможность, т.к. при очень длительных перерывах связи можно будет накапливать сообщения в локальном архиве, хранящемся на ПЛК.
Метода удаления сообщения из архива сообщений я так и не нашел (было бы неплохо попутно с передачей данных подчищать очередь от уже ненужных сообщений, успешно переданных на центральный узел).
ps: с api open-scada я только начал свое знакомство, поэтому могу допустить концептуально неверные выводы...
Written on: 28. 05. 2012 [19:35]
roman
Roman Savochenko
Moderator
Contributor
Developer
registered since: 12.12.2007
Posts: 3750
"DJ-AMIGO" wrote:

Однако, если сервисная функция интерфейса управления для запроса сообщений присутствует, то функции записи нет.

Роман, под сервисной функцией интерфейса управления для запроса сообщений понимается: <get path="/sub_Archive/%2fserv%2fmess"/>

Её.

"DJ-AMIGO" wrote:

Но что Вы имели ввиду под функцией записи? (аналогичная сервисная функция, записывающая сообщение в буфер сообщений?)

Имел в виду <set path="/sub_Archive/%2fserv%2fmess"/>

"DJ-AMIGO" wrote:

Мой поиск и изучение API-OpenSCADA привел меня к следующему:
1. Механизм коммуникации между двумя SCADA-станциями можно попробовать осуществить через встроенный интерфейс управления системой. Среди публичных методов имеется
void cntrCmd( XMLNode *opt, int lev = 0, const string &path = "", int off = 0 ); — Команда работы с интерфейсом управления системы.

API программиста для разработки OpenSCADA. Вам нужно API-пользовательского программирования: http://wiki.oscada.org/Doc/OpisanieProgrammy#h920-1 и там есть функция:
JAVASCRIPT
string cntrReq( XMLNodeObj req, string stat = "" ); — запрос интерфейса управления к системе посредством XML.
Обычный запрос записывается в виде <get path="/OPath/%2felem"/>. При указании станции осуществляется запрос к внешней станции.


Там-же, для получения перечня сообщений из буфера-архива есть:
JAVASCRIPT
Array messGet( int btm, int etm, string cat = "", int lev = 0, string arch = "" ); — запрос системных сообщений за время от <btm> до <etm> для категории <cat>, уровня <lev> и архиватора <arch>.
Возвращается массив объектов сообщений со свойствами:
tm — время сообщения, секунды;
utm — время сообщения, микросекунды;
categ — категория сообщения;
level — уровень сообщения;
mess — текст сообщения.


Learn, learn and learn better than work, work and work.
Written on: 04. 06. 2012 [14:35]
DJ-AMIGO
Михаил Гончаров
Topic creator
registered since: 26.05.2012
Posts: 15
На днях поэкспериментировал с вызовом сервисных функций интерфейса управления OpenSCADA.
Сконфигурировал транспортный уровень, установил соединение между SCADA-станциями по SSL.
С вызовом сервисной функции <get path="/sub_Archive/%2fserv%2fmess"/> проблем не возникло:
JAVASCRIPT
req = SYS.XMLNode("get").setAttr("path","/sub_Archive/%2fserv%2fmess").setAttr("tm",cur_tm).setAttr("tm_grnd",cur_tm-20000).setAttr("cat","").setAttr("lev",0);
SYS.cntrReq(req, "AGLKS");
ret_rez = req.attr("rez");
ret_msg = req.text();
ret_time = req.childGet(1).attr("time");
ret_utime = req.childGet(1).attr("utime");
ret_cat = req.childGet(1).attr("cat");
ret_lev = req.childGet(1).attr("lev");

Возвращает результат без особых сюрпризов:
ret_rez = 0
ret_msg = ""
ret_time, ret_utime, ret_cat и ret_lev содержат значения соотв. атрибутов сообщения

Однако с вызовом указанной Вами сервисной функции <set path="/sub_Archive/%2fserv%2fmess"/> возникли проблемы:
JAVASCRIPT
req = SYS.XMLNode("set").setAttr("path","/sub_Archive/%2fserv%2fmess");
req.childAdd(0).setAttr("time",cur_tm).setAttr("utime",usec_tm).setAttr("cat",cat_str).setAttr("lev",level).setText(mess_str);
req.childAdd(1).setAttr("time",cur_tm).setAttr("utime",usec_tm).setAttr("cat",cat_str).setAttr("lev",level).setText(mess_str2);
SYS.cntrReq(req, "AGLKS");
ret_rez = req.attr("rez");
ret_mcat = req.attr("mcat");
ret_msg = req.text();

Возвращает следующие значения:
ret_rez = 2
ret_mcat = "ContrItfc"
ret_msg = "set:/sub_Archive/%2fserv%2fmess:> Control element '/serv/mess' error!"

Где я допустил ошибку?
Или может быть где-то надо что-то сконфигурировать на отправляющей или принимающей SCADA-станциях?
Требуется ли настройка прав доступа при такого рода взаимодействиях?
Written on: 04. 06. 2012 [22:21]
roman
Roman Savochenko
Moderator
Contributor
Developer
registered since: 12.12.2007
Posts: 3750
"DJ-AMIGO" wrote:

Однако с вызовом указанной Вами сервисной функции <set path="/sub_Archive/%2fserv%2fmess"/> возникли проблемы:
JAVASCRIPT
req = SYS.XMLNode("set").setAttr("path","/sub_Archive/%2fserv%2fmess");
req.childAdd(0).setAttr("time",cur_tm).setAttr("utime",usec_tm).setAttr("cat",cat_str).setAttr("lev",level).setText(mess_str);
req.childAdd(1).setAttr("time",cur_tm).setAttr("utime",usec_tm).setAttr("cat",cat_str).setAttr("lev",level).setText(mess_str2);


В качестве аргумента childAdd лучше укажывать что-то типа "el".

"DJ-AMIGO" wrote:

Возвращает следующие значения:
ret_rez = 2
ret_mcat = "ContrItfc"
ret_msg = "set:/sub_Archive/%2fserv%2fmess:> Control element '/serv/mess' error!"

Где я допустил ошибку?

Не собрали версию с реализацией этой функции или пользователь на сервере, от имени которого туда идут запросы "set" не "root" или не в группе "root".

Learn, learn and learn better than work, work and work.
Written on: 04. 06. 2012 [23:43]
DJ-AMIGO
Михаил Гончаров
Topic creator
registered since: 26.05.2012
Posts: 15
Не собрали версию с реализацией этой функции или пользователь на сервере, от имени которого туда идут запросы "set" не "root" или не в группе "root".

Спасибо, Роман!
Пользователь рутовый!
Заглянул в ChangeLog, и действительно - эту функцию Вы добавили только на прошлой неделе.
Собственно, достаточно ли обновить сборку станции-приемника запросов? Или лучше обновить и сборку станции-источника запросов (на ПЛК)?
Задам глупый вопрос, воможно ли обойтись малой кровью, т.е. пересобрать только один модуль, с реализацией вышеупомянутой функции, для сборки OpenSCADA 0.8.0 LTS?
(В проекте я нашел код реализующий данную функцию в программном модуле tarchives.cpp)
А затем просто заменить старый модуль новым?

[This article was edited 1 times, at last 05.06.2012 at 00:23.]
Written on: 05. 06. 2012 [07:49]
roman
Roman Savochenko
Moderator
Contributor
Developer
registered since: 12.12.2007
Posts: 3750
"DJ-AMIGO" wrote:

Собственно, достаточно ли обновить сборку станции-приемника запросов? Или лучше обновить и сборку станции-источника запросов (на ПЛК)?

Достаточно.

"DJ-AMIGO" wrote:

Задам глупый вопрос, воможно ли обойтись малой кровью, т.е. пересобрать только один модуль, с реализацией вышеупомянутой функции, для сборки OpenSCADA 0.8.0 LTS?
(В проекте я нашел код реализующий данную функцию в программном модуле tarchives.cpp)

Это не в модуле, а в ядре OpenSCADA!

Learn, learn and learn better than work, work and work.
Written on: 03. 07. 2012 [02:29]
DJ-AMIGO
Михаил Гончаров
Topic creator
registered since: 26.05.2012
Posts: 15
Попробовал вызов пользовательской функции:
Array messGet( int btm, int etm, string cat = "", int lev = 0, string arch = "" );
Однако возникла трудность с получение сообщений от конкретного архиватора сообщений!
Если аргумент arch оставить пустым, то выводятся сообщения, находящиеся в данный момент в буфере сообщений.
Но если этому аргументу присвоить имя какого-нибудь конкретного архиватора, то функция всегда возвращает пустой массив.
В архиваторе заведомо имеются сообщения, архиватор включен, остальные параметры поиска подобраны для выборки сообщений, которые в архиве имеются.
Причем пробовал передавать идентификатор архиватора как есть, так и с префиксом "mess_".
Результат один - пустой массив!:bang:
Не подскажете в чем дело?
Written on: 03. 07. 2012 [07:54]
roman
Roman Savochenko
Moderator
Contributor
Developer
registered since: 12.12.2007
Posts: 3750
"DJ-AMIGO" wrote:

Если аргумент arch оставить пустым, то выводятся сообщения, находящиеся в данный момент в буфере сообщений.
...
Не подскажете в чем дело?

Дополнил описание функции:
Array messGet( int btm, int etm, string cat = "", int lev = 0, string arch = "" ); — запрос системных сообщений или нарушений (lev < 0) за время от <btm> до <etm> для категории <cat>, уровня <lev> (-7...7) и архиватора <arch> ("" - буфер и архиваторы; "<buffer>" - буфер; "{ArhMod}.{Arh}" - конкретный архиватор модуля). Возвращается массив объектов сообщений/нарушений со свойствами:
tm — время сообщения, секунды;
utm — время сообщения, микросекунды;
categ — категория сообщения;
level — уровень сообщения;
mess — текст сообщения.


Learn, learn and learn better than work, work and work.



8018