Скрипты
Данная статья актуальна для версий АСУД.SCADA 1.5.0 а3 и выше.
ПО АСУД.SCADA позволяет расширить функционал путем написания специальных программный модулей (скриптов) на языке Lua.
Скрипты находятся в папке Tekon \ ASUD Scada \ Scada \ scripts \ lvm
lvm_entry.lua - загрузчик скриптов - изменять не следует. built-in \ - папка с базовыми скриптами и вспомогательными модулями - изменять не следует custom \ - папка для скриптов пользователей ... \ entry.lua - загрузчик скриптов пользователей
Для создания / редактирования скриптов можно использовать простой Блокнот или воспользоваться специальными утилитами.
Рассмотрим несколько примеров применения скриптов в АСУД.SCADA
1. Текстовое поле + скрипт (вариант 1)
Предположим необходимо задать соответствие числовому значению (Тэга1), получаемому от OPC-сервера, некоторое строковое значение (Str1), и отобразить его в АСУД.SCADA. Например, следующего вида:
- 1 - насос включен.
- 0 - насос выключен.
Внимание, в случае если сигнал в OPC-сервере описан как дискретный датчик, следует проверить его настройку Уровень безопасности, должно быть значение Обычный (иначе если происходит отображение сигнала только в текстовое поле - не будет происходить снятия возникшей аварии).
Сначала опишем скрипт выполняющий соответствующее отображение.
В Блокноте создаем файл pumppwr.lua следующего содержания:
function PumpPower (val,qual)
if qual ~= opc.da.tekon.ItemData.QUALITY_GOOD then
return "---"
end
if val.Integer == 0 then
return "Насос выключен"
end
if val.Integer == 1 then
return "Насос включен"
end
return "Неизвестно"
end
Описывается функция PumpPower с двумя входными параметрами
- val - значение переменной OPC-сервера (тип: Variant)
- qual - значение качества переменной OPC-сервера (тип: Integer)
Для типа Variant допустимы следующие преобразования
.Integer - в целое число .Number - в вещественное число .String - в строку .Date - в переменную типа DateTime .Guid - в guid
Переменная качества может принимать одно из следующих константных значений
opc.da.tekon.ItemData.OPC_QUALITY_BAD opc.da.tekon.ItemData.OPC_QUALITY_UNCERTAIN opc.da.tekon.ItemData.OPC_QUALITY_GOOD opc.da.tekon.ItemData.OPC_QUALITY_CONFIG_ERROR opc.da.tekon.ItemData.OPC_QUALITY_NOT_CONNECTED opc.da.tekon.ItemData.OPC_QUALITY_DEVICE_FAILURE opc.da.tekon.ItemData.OPC_QUALITY_SENSOR_FAILURE opc.da.tekon.ItemData.OPC_QUALITY_LAST_KNOWN opc.da.tekon.ItemData.OPC_QUALITY_COMM_FAILURE opc.da.tekon.ItemData.OPC_QUALITY_OUT_OF_SERVICE opc.da.tekon.ItemData.OPC_QUALITY_WAITING_FOR_INITIAL_DATA opc.da.tekon.ItemData.OPC_QUALITY_LAST_USABLE opc.da.tekon.ItemData.OPC_QUALITY_SENSOR_CAL opc.da.tekon.ItemData.OPC_QUALITY_EGU_EXCEEDED opc.da.tekon.ItemData.OPC_QUALITY_SUB_NORMAL opc.da.tekon.ItemData.OPC_QUALITY_LOCAL_OVERRIDE
Иначе, если значение переменной равно
- 0 - возвращается строка "Насос выключен",
- 1 - "Насос включен"
- иначе вернется строка "Неизвестно".
Следует отметить, что приведенный вариант реализации функции PowerPump не единственный, можно привести следующий равнозначный вариант кода:
PumpToStr=
{
[0] = "Насос выключен",
[1] = "Насос включен"
}
function PumpPower2 (val, qual)
if qual ~= opc.da.tekon.ItemData.QUALITY_GOOD then
return "---"
end
local text = PumpToStr[val.Integer]
if text ~= nil then
return text
end
return "Неизвестно"
end
Далее, сохраняем файл в папке scripts \ lvm \ custom
Открываем в Блокноте файл scripts \ lvm \ custom \ entry.lua и добавляем в первой строке запись
- dofile2("pumppwr.lua")
dofile2("pumppwr.lua")
function main_custom()
end
Сохраняем файл.
Далее запускаем программу АСУД.SCDA.
Размещаем примитив "Текстовое поле". Задаем его свойства:
- Тэг - Тэг1.
- Скрипт \ OnDataChange - PumpPower
Сохраняем настройки АСУД.SCADA
После этого должны увидеть что в Текстовом поле отображается строковое значение, в соответствии с логикой скрипта.
Рассмотренный пример можно загрузить здесь
2. Текстовое поле + скрипт (вариант 2)
В данном варианте рассматривается возможность не только отображения, но и записи в OPC-сервер значения указанного пользователем.
Данная возможность может быть актуальна, например, при диспетчеризации и управлении сторонним оборудованием, подключаемым по протоколу Modbus.
При этом отображение текущего значения происходит в примитиве Текстовое поле, а при двойном нажатии на примитив открывается окно, в котором пользователю предлагается ввести новое значение.
Возможности:
- чтение числового значения
- запись числового значения
Вид окна редактирования:
- Окно с текстовым полем (для ввода значения)
Удобно при необходимости простого изменения числового значения
- Окно с выпадающим списком (для выбора значения из списка)
Удобно при изменении значения перечисляемого типа. Например, как в случае с насосом, в варианте 1.
Сначала опишем скрипт.
В Блокноте следует открыть файл scripts \ lvm \ custom \ gui.lua
Данный файл содержит описание базовых классов, обеспечивающих работу с окнами редактирования параметров. В большинстве случаев изменять их не следует.
Переходим в конец файла и ищем строку -- Создание объектов
-------------------------------------------------------------------------------------------------------------------
-- Создание объектов.....
-------------------------------------------------------------------------------------------------------------------
topc_object0 = topc_string_primitive("Объект Edit", WTYPE_EDIT)
topc_object2 = topc_combo ("Объект ComboBox", WTYPE_COMBOBOX)
-- Нумерация элементов по умолчанию с 1
combo2=
{
[0] = "Отключено",
[1] = "Запуск",
[2] = "ДежЛето",
[3] = "Охлажд",
[4] = "Вентиляц",
[5] = "ДежЗима",
[6] = "Прогрев",
[7] = "Нагрев",
[8] = "Обратная",
[9] = "Замерз",
[10] = "АНР Тпр Л",
[11] = "АНР Тпр З",
[12] = "АНР Тобр Д"
}
topc_object2:Elements (combo2)
topc_object1 = topc_combo ("Объект ComboBox", WTYPE_COMBOBOX)
-- Нумерация элементов по умолчанию с 1
combo1=
{
[0] = "Выкл",
[1] = "Вкл"
}
topc_object1:Elements (combo1)
В данном случае создаются объекты:
- topc_object0 - окно с текстовым полем
- topc_object1 - окно с выпадающим меню (элементы меню перечислены в combo1)
- topc_object2 - окно с выпадающим меню (элементы меню перечислены в combo2)
Следует внести изменения в перечисления combo1, combo2 в соответствии с получаемыми данными. По необходимости создать собственные объекты по аналогии.
Сохранить файл.
Далее открываем в Блокноте файл scripts \ lvm \ custom \ entry.lua и добавляем в первой строке запись
- dofile2("gui.lua")
dofile2("gui.lua")
function main_custom()
end
Сохраняем файл.
Далее запускаем программу АСУД.SCDA.
Размещаем примитив "Текстовое поле 1". Задаем его свойства:
- Тэг - Тэг1.
- Скрипт \ LVM объект - topc_object0
Размещаем еще один примитив "Текстовое поле 2". Задаем его свойства:
- Тэг - Тэг2.
- Скрипт \ LVM объект - topc_object1
Внимание, в поле Скрипт следует указывать
- либо LVM объект
- либо функцию OnDataChange (как указано в примере 1).
Сохраняем настройки АСУД.SCADA
3. Анализ изменений сигнала (автомат управления)
Рассмотрим пример простого скрипта, реализующего выключение канала управления КУП-RS подключенного к концентратору Мини-КУН номер 210, при срабатывании дискретного входа номер 4 на концентраторе Мини-КУН номер 202.
Предполагаем, что уже существует настройка OPC-сервера, для концентраторов 210 и 202
Создадим текстовый файл с именем script1.lua в блокноте следующего содержания:
-- описываем карту связи Датчик - Канал управления
-- тэги просто копируем из свойства Тэг примитива АСУД.SCADA
descret_autocall_task_map =
{
["DA.[localhost{188D08EC-72CB-425B-8EA8-EE2308736440}].USB Пульт.202 Мини-КУН.Авария 1"] =
"DA.[localhost{188D08EC-72CB-425B-8EA8-EE2308736440}].USB Пульт.210 Мини-КУН.КУП Канал 1.Остановка"
}
-- в эту функцию будет приходить любые события связанные с изменением состояния датчиков
function DescretSensor_OnDataChange(topc_item, topc_itemdata)
-- проверка данных на валидность
if topc_item~= nil and topc_itemdata~=nil then
if topc_itemdata.Quality ~= opc.da.tekon.ItemData.QUALITY_GOOD or topc_itemdata.Data ==nil then
return
end
-- запрос значения датчика
local int = topc_itemdata.Data.Integer
-- запрос типа датчика
local prop = item:GetProperty(opc.da.tekon.Item.ITEM_TYPE)
-- проверка того, что датчик дискретный
if prop ~= nil and prop.Data.Integer == opc.da.tekon.Item.SENSOR then
if descret_autocall_task_map[topc_item.ItemID] ~= nil then
-- запрос указателя на канал управления связанный с дискретным датчиком
local itemCtrl, bRes = opc.da.tekon.GetItem(descret_autocall_task_map[topc_item.ItemID])
if (itemCtrl~= nil) and bRes then
-- если дискретный датчик активен, выключить канал управления
if int==32769 then
local newData = base.Variant(0);
itemCtrl:AsyncWrite(newData)
end
end
end
end
end
end
-- функция инициализации скрипта
function InitScript1()
-- подписаться на событие (изменение состояния любого датчика)
opc.da.tekon.RegisterEventHandler(
"OPC::DA::TEKON::OnDataChange",
"DescretSensor_OnDataChange")
-- подписаться на событие чтение состояния датчика
opc.da.tekon.RegisterEventHandler(
"OPC::DA::TEKON::OnReadComplete",
"DescretSensor_OnDataChange")
end
Значения дискретного датчика могут быть следующие:
32769 - активная авария (красный воскл.знак на примитиве); 32771 - активная авария, с которой ознакомился диспетчер (желтый воскл.знак на примитиве); 0 - нет аварии.
Подробнее см. дискретные сигналы Tekon OPC DA
Команды каналу управления могут быть следующие:
0 - выключить канал управления; 1 - включить канал управления.
Сохраните файл script1.lua
Откройте в блокноте файл ..scripts\lvm\custom\entry.lua и внесите следующие изменения:
dofile2("gui.lua")
dofile2("script1.lua")
function main_custom()
InitScript1()
end
Сохраните файл, запустите АСУД.SCADA, логика созданного автомата управления должна работать.
Ссылки
Дискретный_сигнал_(OPC-сервер)
--Alex 12:21, 5 июля 2013 (UTC)