Скрипты: различия между версиями

Материал из TekonWiki
Перейти к навигацииПерейти к поиску
Строка 56: Строка 56:
В Блокноте создаем файл pumppwr.lua следующего содержания:
В Блокноте создаем файл pumppwr.lua следующего содержания:


<source lang="javascript" collapse="true" first-line="2">
<source lang="php">
function Pump (val,qual)
function Pump (val,qual)
  local PumpToStr =  
  local PumpToStr =  
Строка 115: Строка 115:
* dofile2("pumppwr.lua")
* dofile2("pumppwr.lua")


<nowiki>
<source lang="php">
dofile2("pumppwr.lua")
dofile2("pumppwr.lua")


function main_custom()
function main_custom()


end</nowiki>
end
</source>


Сохраняем файл.
Сохраняем файл.

Версия от 19:16, 21 ноября 2014


Данная статья актуальна для версий АСУД.SCADA 1.5.6 (и выше).

ПО АСУД.SCADA позволяет расширить функционал путем написания специальных программный модулей (скриптов) на языке Lua. Скрипты выполняются на стороне рабочей программы SCADA.

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

Поддерживаются спецификации:

В настоящее время отсутствует встроенная в программное обеспечение возможность отладки/компиляции скрипта. Поэтому если при запуске SCADA появляется сообщение с информацией об ошибке Lua, следует проверить правильность написания скрипта.

Скрипты находятся в папке Tekon \ ASUD Scada \ Scada \ scripts \ lvm. Каталог имеет следующую структуру и содержание:

  • lvm_entry.lua - общий загрузчик скриптов - изменять не следует.
  • built-in \ - папка со скриптами и вспомогательными модулями, разработанными специалистами Текон-Автоматика. Изменять и/или редактировать файлы не следует.
  • custom \ - папка для скриптов пользователя
    • .. \ entry.lua - загрузчик скриптов пользователя

Скрипты в папке built-in \ могут изменяться при обновлении программного обеспечения АСУД.SCADA. Папка custom \ - не обновляется при обновлении ПО.

Для создания / редактирования скриптов можно использовать:

  • простой Блокнот,
  • программу Notepad ++
  • специальную среду разработки, например, wxLua.

Любые изменения в скриптах вступают в силу после перезапуска АСУД.SCADA.

Внимание

Скрипты могут быть использованы, например, для преобразования числового значения получаемого от OPC-сервера в строку. При этом следует обратить внимание на особенности представления дискретных сигналов Tekon OPC DA сервером.

Для дискретного датчика, следует проверить настройку Уровень безопасности, в общем случае должно быть значение Обычный (если отображение сигнала происходит только в текстовом поле, без связки с примитивами типа дискретный датчик (дверь, лифт и т.п.), т.к. в противном случае не будет происходить снятия возникшей аварии).

Т.е. если тэг будет связан с:

  • текстовое поле - уровень безопасности следует установить только в "Обычный"
  • текстовое поле + примитив - уровень безопасности "Охрана" или "Обычный".

Рассмотрим несколько вариантов применения скриптов в АСУД.SCADA

Преобразовать число в строку

Задача

Необходимо задать соответствие числовому значению (Тэга1) OPC-сервера некоторое строковое значение (Str1), и отобразить его в АСУД.SCADA.

Например, следующего вида:

  • 0 - насос выключен.
  • 1 - насос включен.

Решение

Сначала опишем скрипт выполняющий соответствующее отображение.

В Блокноте создаем файл pumppwr.lua следующего содержания:

function Pump (val,qual)
 local PumpToStr = 
 { 
 [0] = "Насос включен", 
 [1] = "Насос выключен"
 }
 if qual ~= opc.da.tekon.ItemData.QUALITY_GOOD then
		return "---"
 end
 -- проверяем значение Тега только на 0 или 1
 return PumpToStr [hasbit_ex(val.Integer,1)]
end

Вначале описывается функция Pump с двумя входными параметрами

  • 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

Обычно достаточно просто проверить со значением opc.da.tekon.ItemData.QUALITY_GOOD.

Таблица PumpToStr определяет взаимное соответствие значения переменной строке.

Проверка значения только первого бита (биты байта 8...2,1) переменной (val.Integer), а не значения val.Integer в целом, связана опять же с представлением дискретного сигнала в Tekon OPC DA сервере.

Далее, сохраняем файл в папке scripts \ lvm \ custom

Открываем в Блокноте файл scripts \ lvm \ custom \ entry.lua и добавляем в первой строке запись

  • dofile2("pumppwr.lua")
dofile2("pumppwr.lua")

function main_custom()

end

Сохраняем файл.

Далее запускаем программу АСУД.SCDA.

Размещаем примитив "Текстовое поле". Задаем его свойства:

  • Тэг - Тэг1.
  • Скрипт \ OnDataChange - Pump

Сохраняем настройки АСУД.SCADA

После этого должны увидеть, что в Текстовом поле отображается строковое значение, в соответствии с логикой скрипта.

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

Рассмотренный пример можно загрузить здесь

Преобразовать число

Задача

Необходимо преобразовать числовое значение (Тэга1) OPC-сервера в соответствии с некоторой формулой, и отобразить его в АСУД.SCADA.

Например, пусть в Тэге1 хранится значение теплосчетчика в кВт*ч, а необходимо отобразить его в АСУД.SCADA в ГКал

Решение

Известно, что 1 кВт*ч = 0.000860 ГКал

Сначала опишем скрипт выполняющий соответствующее преобразование:


function round(num, idp)
  local mult = 10^(idp or 0)
  return math.floor(num * mult + 0.5) / mult
end

function VT2GKAL (val,qual)
 if qual ~= opc.da.tekon.ItemData.QUALITY_GOOD then
		return "---"
 end
 local GKal =  val.Number *  0.000860
 return    (round(GKal, 3)) .. " ГКал"
end

Скрипт выводит значение в ГКал с точностью до 3-его знака после запятой.

Далее, сохраняем файл в папке scripts \ lvm \ custom как VT2GKAL.lua

Аналогично примеру 1 Открываем в Блокноте файл scripts \ lvm \ custom \ entry.lua и добавляем в первой строке запись

dofile2("VT2GKAL.lua")

Сохраняем файл.

Далее запускаем программу АСУД.SCDA.

Размещаем примитив "Текстовое поле". Задаем его свойства:

  • Тэг - Тэг1.
  • Скрипт \ OnDataChange - VT2GKAL

Сохраняем настройки АСУД.SCADA

После этого должны увидеть, что в Текстовом поле отображается строковое значение, в соответствии с логикой скрипта.

Запуск внешнего приложения из Scada

Задача

Дать возможность диспетчеру периодически запускать из SCADA программы Блокнот, Калькулятор, Интернет-Браузер

Решение

Для реализации заданного функционала необходимо подключить файл ...Scada/scripts/lvm/build-in/open_link.lua

Открыть в блокноте файл ...Scada/scripts/lvm/custom/entry.lua и отредактировать его

dofile2("..\\build-in\\open_link.lua")

tlink = topc_link ("www.ya.ru")
tlinkNotepad = topc_link ("notepad.exe")
tlinkCalc = topc_link ("calc.exe")

function main_custom()

end
 

Будут созданы три объекта:

  • tlink - открывающий Интернет-браузер на странице www.ya.ru
  • tlinkNotepad - открывающий приложение Блокнот
  • tlinkCalc - открывающий приложение Калькулятор

Закрыть файл, подтвердив его сохранение.

Запускаем SCADA и отображаем, например, на главном виде три примитива "Текстовое поле"

Запуск внешнего приложения

Далее последовательно в свойствах каждого примитива указываем соответствующий LVM-объект обработки двойного нажатия мыши.

Для текстового поля "Браузер" указываем tlink

Запуск внешнего приложения

Для текстового поля "Блокнот" - tlinkNotepad, для поля "Калькулятор" - tlinkCalc

Сохраняем изменения, переходим в рабочий режим.

Теперь при при двойном нажатии на примитив будет запускаться соответствующая внешняя программа.


Запись значения введенного пользователем на Сервер

Задача

Помимо задачи примера 1, следует иметь возможность записи в OPC-сервер значения указанного пользователем.

Данная задача может быть актуальна, например, при диспетчеризации и управлении сторонним оборудованием, подключаемым по протоколу Modbus.

При этом отображение текущего значения должно происходить в примитиве Текстовое поле, а при двойном нажатии на примитив открываться окно, в котором пользователю предлагается ввести новое значение, которое затем должно быть записано в ОРС-сервер.


Решение

Для решения подобных задач разработаны два базовых "класса", реализующих следующие возможности:

  • чтение числового значения из Сервера
  • преобразование прочитанного значения перед отображением в SCADA
  • запись числового значения введенного пользователем в Сервер

Пользователю доступно два варианта окна ввода новых данных:

  • Окно с текстовым полем - класс topc_string. Удобно при необходимости простого изменения числового значения
  • Окно с выпадающим списком - класс topc_сombo. Удобно при изменении значения перечисляемого типа. Например, как в случае с насосом в варианте 1.
Окно с текстовым полем
Окно с выпадающим списком

Функционал базовых "классов" представлен в файлах:

  • \build-in\gui_basic.lua - отрисовка окон
  • \build-in\prim_basic.lua - поведение объектов

Данные файлы снабжены подробными комментариями.

Для создания объекта "класса" и использовании его в SCADA следует в Блокноте следует открыть (создать) файл scripts \ lvm \ custom \ gui_object.lua следующего содержания:

dofile2 ("..\\built-in\\prim_basic.lua")

topc_object0 = topc_string(" [Комментарий]")

local combo1 =
{
[0] = "Выкл",
[1] = "Вкл"
}

topc_object1 = topc_combo (" [Комментарий]", combo1)

В данном случае создаются объекты:

  • topc_object0 - окно с текстовым полем
  • topc_object1 - окно с выпадающим меню (элементы меню перечислены в combo1)

Следует внести изменения в перечисление combo1 в соответствии с получаемыми данными. По необходимости создать собственные объекты по аналогии.

Сохранить файл.

Далее открываем в Блокноте файл scripts \ lvm \ custom \ entry.lua и добавляем в первой строке запись

  • dofile2("gui_object.lua")
dofile2("gui_object.lua")

function main_custom()

end

Сохраняем файл.

Далее запускаем программу АСУД.SCADA.

Размещаем примитив "Текстовое поле 1". Задаем его свойства:

  • Тэг - Тэг1.
  • Скрипт \ LVM объект - topc_object0

Размещаем еще один примитив "Текстовое поле 2". Задаем его свойства:

  • Тэг - Тэг2.
  • Скрипт \ LVM объект - topc_object1

Внимание, в поле Скрипт можно указывать, что-то одно:

  • либо LVM объект
  • либо функцию OnDataChange (как указано в примере 1).

Следует иметь ввиду, что объекты topc_object0 и topc_object1 могут быть использованы в настройках нескольких примитивов Текстовое поле (в том числе и с разными Тэгами).

Сохраняем настройки АСУД.SCADA

В случае необходимости создания собственно окна и "класса" поведения объекта, вы можете воспользоваться для примера файлами, реализующие функционал работы с устройством ОВЕН ПЧВ:

  • built-in \ qui_owen_pchv.lua
  • built-in \ prim_owen_pchv.lua
Окно ОВЕН ПЧВ

Анализ изменений сигнала (автомат управления)

Задача

Реализовать выключение канала управления при срабатывании дискретного датчика.

Внимание! Начиная с версии АСУД.SCADA 1.5.8 данный функционал может быть настроен непосредственно в программе, подробнее смотри Автоматическое управление устройствами

Решение

Рассмотрим пример простого скрипта, реализующего выключение канала управления КУП-RS подключенного к концентратору Мини-КУН номер 210, при срабатывании дискретного входа номер 4 на концентраторе Мини-КУН номер 202.

Предполагаем, что уже существует настройка OPC-сервера, для концентраторов 210 и 202

Создадим текстовый файл с именем avtomat.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 LocalAvto_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 = topc_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 hasbit_ex (int,1) == 1 then
               local newData = base.Variant(0);
               itemCtrl:AsyncWrite(newData)
            end
           end				
        end
   end	  
  end
 end
 
 -- функция инициализации скрипта
 function InitAvtomat()
  -- подписаться на событие (изменение состояния любого датчика)
  opc.da.tekon.RegisterEventHandler(
     "OPC::DA::TEKON::OnDataChange",
     "LocalAvto_OnDataChange")
  -- подписаться на событие чтение состояния датчика 
  opc.da.tekon.RegisterEventHandler(
     "OPC::DA::TEKON::OnReadComplete",
     "LocalAvto_OnDataChange")
 end


Функция LocalAvto_OnDataChange вызывается

  • один раз при старте АСУД.SCADA при первоначальном получении значений тэгов (событие OPC::DA::TEKON::OnReadComplete)
  • всякий раз при изменении значения любого тэга Tekon OPC DA сервера (событие OPC::DA::TEKON::OnDataChange).

Команды каналу управления могут быть следующие:

0 - выключить канал управления;
1 - включить канал управления.

Сохраните файл avtomat.lua

Откройте в блокноте файл ..scripts\lvm\custom\entry.lua и внесите следующие изменения:

 dofile2("avtomat.lua")

 function main_custom()
  InitAvtomat()
 end



Сохраните файл, запустите АСУД.SCADA, логика созданного автомата управления должна работать.

Рассмотренный пример можно загрузить здесь

Канал управления без подключения обратной связи

См. Канал управления без подключения обратной связи

Задача

Реализовать следующую логику работы примитива канал управления:

  1. включение
  2. отображение состояния "включаюсь"
  3. перевод примитива в исходное состояние (выключен).


Внимание! Начиная с версии АСУД.SCADA 1.5.8 данный функционал может быть настроен непосредственно в программе, подробнее смотри Автоматическое управление устройствами

Решение

Для решения задачи воспользуемся модифицированным скриптом из примера 3.

Создадим текстовый файл с именем ..scripts\lvm\custom\domofone.lua в блокноте следующего содержания:

-- Ниже необходимо указать тэги всех каналов управления, подключенных
-- без обратной связи (например, к блоку сопряжения с Домофоном)
-- нумерация 1,2,3 просто сквозная и не имеет никакого значения.
task_map = 
{
 ["DA.[localhost{188D08EC-72CB-425B-8EA8-EE2308736440}].КУН - 102.Канал управления 1"] = 1,
 ["DA.[localhost{188D08EC-72CB-425B-8EA8-EE2308736440}].КУН - 102.Канал управления 2"] = 2,
 ["DA.[localhost{188D08EC-72CB-425B-8EA8-EE2308736440}].КУН - 212.Канал управления 1"] = 3
}
-- Функция вызывается при изменения состояния любого датчика
function Local_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	
   end
  -- запрос типа датчика
  local prop = topc_item:GetProperty(opc.da.tekon.Item.ITEM_TYPE) 
  -- проверка того, что это канал управления
  if prop ~= nil and prop.Data.Integer == opc.da.tekon.Item.CONTROL_CHANNEL then 
    -- проверка что канал управления описан task_map
     if task_map[topc_item.ItemID] ~= nil then 
      -- Значение = 1 ? Канал, находится в состоянии включаюсь ?
      if topc_itemdata.Data.Integer == 1 then 
       -- подождать 1 секунду и сбросить значение в 0
       wx.wxSleep(1)  	   
       local newData = base.Variant(0)
       topc_item:AsyncWrite(newData)
      end
    end 
  end	  
end
 
 -- функция инициализации скрипта
 function InitDomofone()
  -- подписаться на событие изменение состояния датчика
  opc.da.tekon.RegisterEventHandler(
     "OPC::DA::TEKON::OnDataChange",
     "Local_OnDataChange")
  -- подписаться на событие чтение состояния датчика 
  opc.da.tekon.RegisterEventHandler(
     "OPC::DA::TEKON::OnReadComplete",
     "Local_OnDataChange")
 end

Основные изменения, которые необходимо произвести - лишь прописать тэги каналов управления, подключенные к блоку домофона в task_map

task_map = 
{
 ["DA.[localhost{188D08EC-72CB-425B-8EA8-EE2308736440}].КУН - 102.Канал управления 1"] = 1,
 ["DA.[localhost{188D08EC-72CB-425B-8EA8-EE2308736440}].КУН - 102.Канал управления 2"] = 2,
 ["DA.[localhost{188D08EC-72CB-425B-8EA8-EE2308736440}].КУН - 212.Канал управления 1"] = 3
}

Сохраните файл.

Откройте в блокноте файл ..scripts\lvm\custom\entry.lua и внесите следующие изменения: dofile2("domofone.lua") function main_custom() InitDomofone() end

Сохраните файл, запустите АСУД.SCADA, логика созданного автомата управления должна работать.

Рассмотренный пример можно загрузить здесь


Ссылки

Дискретный сигнал Tekon OPC DA

Вспомогательные файлы *.cpp (пространство opc.da.tekon, базовые типы) можно загрузить здесь


--Alex 12:21, 5 июля 2013 (UTC)