Скрипты

Материал из TekonWiki
Перейти к: навигация, поиск

 

 



Содержание

Введение

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

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

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

Замечание:
В ряде случаях, для решения простой задачи сопоставления Число = Значение в SCADA,  
вы можете воспользоваться альтернативным решением: Text-функцией

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

В настоящее время отсутствует встроенная в программное обеспечение возможность отладки/компиляции скрипта. 

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

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

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

Папка custom \ - не обновляется при обновлении ПО.

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

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

Скрипты следует создавать только в папке \ scripts \ lvm \ custom \   

Вы моежете создать скрипт в отдельном текстовом файле с раширением lua и подключить этот файл, добавив в \ scripts \ lvm \ custom \entry.lua запись 

dofile2 ("имя_файла.lua")

Или записать текст скрипта (если он небольшой) непосредственно в файле \ scripts\lvm\custom\entry.lua

Файл скрипта следует сохранять в кодировке ANSI (Windows charset).

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

Во время отладки скриптов удобно запускать SCADA в специальном режиме  (без отображения заставки). Для этого следует выполнить файл scada-no-splash.bat  или, если данный файл отсутствует запустить scada.exe c ключом

scada.exe --no-splash

В противном случае, если скрипт содержит ошибку, вы не увидите ее, т.к. она будет скрыта за картинкой заставки.

В зависимости от логики скрипт может быть:

  • связан с примитивом типа Текстовое поле, Изображение и т.п. 
  • или работать без связки с примитивами (в фоновом режиме).

Скрипты, связываемые с Текстовым полем условно делятся на две группы:

  • скрипты функции - позволяют выполнить простое преобразование данных перед их визуализаций на ситуационном плане АСУД.SCADA (подобную логику вы можете реализовать и с помощью Text-функция)
  • скрипты LVM-объекты - позволяют реализовать более сложную логику работы, создавать новые окна и т.п.

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

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

Т.е. если тэг  Item  типа дискретный сигнал будет связан:

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

Ссылки

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

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

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

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

Задача

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

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

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

(данная задача также может быть решена с применением Text-функции)

Решение

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

В Блокноте создаем файл 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)

Для val допустимы следующие преобразования

 
 .Integer - в целое число 
 .Number - в вещественное число 
 .String - в строку 
 .Date - в переменную типа DateTime 
 .Guid - в guid 

Переменная качества qual может принимать одно из следующих константных значений

 
 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 

Обычно достаточно просто проверить qual со значением 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.
  • Скрипт \ OnDataChanged - Pump

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

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

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

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

Преобразовать состояние АКБ КИР в строку

Задача

Необходимо задать соответствие числовому значению (Тэга) состояния АКБ концетратора КИР-16 исп. TL-RS OPC-сервера текстовой строке, и отобразить его в АСУД.SCADA.

Данная задача может быть решена с применением Text-функции

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

Задача

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

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

Решение

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

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

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

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

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

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

dofile2("VT2GKAL.lua")

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

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

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

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

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

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

 


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

Для создания объектов данного типа вы также можете воспользоваться утилитой SCRIPT MAKER.EXE

Также вы моежете воспользоваться функционалом примитива Кнопка.

Задача

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

Решение 1

Использовать примитив Кнопка

Решение 2

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

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

 
 dofile2("..\\built-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

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

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

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

2.7.17 
+ добавлена возможность проверки значения ведущего сигнала
перед открытием окна изменения значения
+ добавлена возможность отображения в текстовом поле указанного слова, 
вместо текущего значения, связанного Item

Для создания объектов данного типа вы можете воспользоваться утилитой SCRIPT MAKER.EXE
(если необходима функция проверки мастер-сигнала перед записью, созданные скрипты необходимо будет отредактировать вручную).

Задача

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

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

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

Решение

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

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

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

  • topc_string - окно с текстовым полем. Удобно при необходимости простого изменения числового значения
  • topc_string_min_max - окно с текстовым полем, аналог topc_string с проверкой граничных значений
  • topc_сombo - окно с выпадающим списком. Удобно при изменении значения перечисляемого типа (число = значение), например: 0 - Включить, 1 - Выключить. Перечисление должно идти непрерывно с 0 или 1.
  • topc_сombo_ex (с версии 2.3.2) - окно с выпадающим списком. Удобно при изменении значения перечисляемого типа (число = значение), например: 1024 - Включить, 2983 - Выключить. Перечисление в отличие от topc_сombo может идти как угодно.
Окно с текстовым полем topc_string
Окно с текстовым полем и границами topc_string_min_max
Окно с выпадающим списком topc_сombo или topc_сombo_ex

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

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

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

Для создания объекта "класса" и использовании его в SCADA следует

  • закрыть SCADA
  • в Блокноте открыть файл scripts \ lvm \ custom \ entry.lua

и добавить в него нужный набор объектов, например:dofile2 ("..\\built-in\\prim_basic.lua")

-- добавить строки, если не было 
dofile2 ("..\\built-in\\prim_basic.lua")

-- просто строка, имя topc_object0 может быть любым
topc_object0 = topc_string(" [Комментарий]")

-- строка с проверкой вводимого значения, имя topc_object2 может быть любым
topc_object2 = topc_string_min_max ("  Комментарий",0,100)

-- элементы списка
local combo_ex1 =
{
[10] = "Выкл",
[20] = "Вкл"
}

-- выпадающий список элементов, имя topc_object_ex1 может быть любым
topc_object_ex1 = topc_combo_ex (" [Комментарий]", combo_ex1)

-- ....
function main_custom() 

end

Пример поведения topc_object_ex1

  • если с сервера придет значение 10, в текстовом поле отобразится Выкл
  • если выбрать в текстовом поле Вкл, в сервер запишется число 20.

По необходимости создать собственные объекты по аналогии.

Следует отметить:

  • объекты универсальны,
  • один объект может быть связан с многими примитивами Текстовое поле на карте
    (в том числе с разными тегами)

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

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

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

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

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

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

Аналогично добавляется topc_object2

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

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

  • built-in \ qui_owen_pchv.lua
  • built-in \ prim_owen_pchv.lua
Окно ОВЕН ПЧВ
Замечание: 
Eсли скрипт связан с примитивом Текстовое поле, то в случае, если OPC-Item имеет плохой статус (нет связи с устройством) в текстовом поле вы увидите прочерки "---", и созданное вами окно в рабочем режиме открываться не будет. 
Scrip badstatus.PNG

Проверка перед записью значения другого Item

В версии 2.7.17 появилась возможность предварительной проверки значения любого указанного сигнала SCADA перед открытием окна записи нового значения.

Если значение этого ведущего сигнала не удовлетворяет условиями проверки, окно записи нового значения открыто не будет, а пользователь будет проинформирован об ошибке.

Это может потребоваться, например в устройствах, в которых запрещается изменять значение параметра1, если параметр2 (ведущий сигнал) не находится в опреденных границах.

Script check master signal.PNG

Данная возможность есть у всех рассмотренных ранее классов. Для ее активации необходимо дополнить строку создания  объекта класса в файле
custom \ entry.lua следующими параметрами, например:

topc_object2 = topc_string_min_max (" Комментарий",0,100,master_name,master_endname, master_func, master_comment)

, где:

  • master_name - полное имя тега ведущего сигнала
  • master_endname - окончание имени ведущего сигнала, в случае указания, скрипт сам выполнит определение полного имени, исходя из указанного имени Тега, связанного с Текстовым полем.
    Например: Тег  = DA.[localhost...].КУН-IP8.Modbus-RTU-1.Открытие двери
    master_endname = Сигнал проверки, 
    тогда master_name будет определен, как   DA.[localhost...].КУН-IP8.Modbus-RTU-1.Сигнал проверки
  • master_func - функция проверки значения, с одним входым параметром Data
    запись значения разрешена, если функция возращает true.
  • master_comment - (не обязательный) комментарий, который будет отображен в сообщении об ошибке 

Вы должны указывать настройку либо master_name либо master_endname, скрипт анализирует только одно из этих значений.

Если указываете  master_name - то для каждого текстового поля, придется использовать создавать свой объект, если  ведущие сигналы отличаются друг от друга.

master_endname - более универсальное решение, для однотипно настроенных устройств

Примеры: 

-- если значение мастер-сигнала 0, записывать новое значение - можно
local function CheckFunc (Data)
 if Data.Integer == 0 then 
   return true
 end
 return false 
end

topc_object2 = topc_string_min_max (" Комментарий",0,100,"","Сигнал проверки", CheckFunc, "")


Регистры чтения / записи значения отличаются друг от друга 

Возможность доступна с версии 2.7.17

Обычно значения параметра-уставки читаются и записываются из одного регистра данных. 

Однако, в некоторых случаях, у устройства для записи значения может использоваться отдельный регистр, например:

  • читаем текущее значение из регистра А
  • меняем текущее значение, путем записи нового в регистр В

 В этом случае для визуализации данных необходимо использовать два элемента , например: два текстовых поля

  • одно для отображения текущего значения регистра А
  • второе, , связанное с lua-объектом, для записи нового в регистр В
Scripts sample 2registrs.PNG
Особенность отображения в данном случае заключается в том, что во втором текстовом поле не надо отображать текущее значение Item-а. Эта возможность реализуется с помощью специальной настройки  lua-объекта.

Следует в файле lua-скрипта в первом строковом параметре вначале добавить ! (восклицательный знак), например:

  • ! - в текстовом поле будет отображаться слово Настроить
  • !Задать - в текстовом поле будет отображаться слово Задать

Примеры:

topc_object2 = topc_string_min_max ("! Комментарий",0,100)  
topc_object3 = topc_string_min_max ("!Задать Комментарий",0,100)
topc_object4 = topc_string_min_max ("!",0,100)

Отображение Min, Max, Avg для цифрового параметра

Для создания объектов данного типа вы можете воспользоваться утилитой SCRIPT MAKER.EXE

Задача

Для цифрового значения, получаемого от OPC-сервера отобразить min, max, avg

Решение

Для решения задачи в файле \\built-in\\prim_basic.lua реализован "класс" topc_minmaxavg.

Объект класса не умеет записывать данные на сервер и выполняет только анализ и отображение данных в Текстовое поле.

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

 

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

topc_minmax = topc_minmaxavg ("1",1,1,1)

function main_custom()

end

Параметры конструктора topc_minmaxavg (primname,digit,navg,show_time) определяют вид отображения данных:

  • primname - просто текстовое имя (резерв)
  • digit - число знаков после запятой: 1, 2, ....
  • navg = 0 не отображать Avg, 1 - отображать
  • show_time = 0 не отображать Время, 1 - отображать

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

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

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

  • Тэг - Тэг1.
  • Скрипт \ LVM объект - topc_minmax
  • Скрыть линию - Да
  • Заливка - белая

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

Рассмотрим различные варианты отображения данных в зависимости от параметров конструктора объекта topc_minmaxavg

Пример отображения данных
  • topc_minmax0 = topc_minmaxavg ("1",1,0,0)
  • topc_minmax1 = topc_minmaxavg ("1",1,0,1)
  • topc_minmax2 = topc_minmaxavg ("1",1,1,0)
  • topc_minmax3 = topc_minmaxavg ("1",1,1,1)

 

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

Задача

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

Внимание! Начиная с версии АСУД.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, логика созданного автомата управления должна работать.

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

Анализ изменений сигнала (вариант 2)

Задача

Реализовать возможность  записи числового значения в ведомый Item, в зависимости от числового значения Главного Item OPC-сервера.  Оба Item имеют тип - Числовое значение.

Решение

Следует скопировать файл masterslaveitems.lua из папки \ script \ built-in \  в папку  \ script \ custom \  и отредактировать его (если файл отсутствует вы можете загрузить его по ссылке

-- СЕКЦИЯ НАСТРОЕК

-- Следует указать Теги сопоставление Главный сигнал и Ведомый сигнал в exclib__mapDependency  
-- Например: Temperature01 - главный сигнал, OutSignal1 - ведомый

local exclib__mapDependency  = 
{
	["DA.[localhost{188D08EC-72CB-425B-8EA8-EE2308736440}].КУН-IP8 - 0.Temperature01"] =
		"DA.[localhost{188D08EC-72CB-425B-8EA8-EE2308736440}].DAServerInfo.OutSignal1"
}

-- Следует указать сопоставление значений Главного сигнала и Ведомого

local  value_map = 
{
 [0] = 0,
 [1] = 1
}

--[[ 
 [0] = 0,       - при 0 записать 0
 [1] = 1        - при 1 записать 1
Дополнительные примеры 

 [0] = 0,       - при 0 записать 0
 [1] = 2        - при 1 записать 2
 
 [0] = nil      - при 0 ничего не делать
 [1] = 1        - при 1 записать 1
]]

-- Следует указать, что записать в Ведомый, если пропала связь с Главным (плохой ОРС-статус)

local NC_WriteToSlave = 0;  -- или nil  если ничего не надо записывать


-- КОНЕЦ СЕКЦИИ НАСТРОЕК

Следует внести изменения в секцию Настроек: 

  • в таблице exclib__mapDependency  указать соответствие Ведущий - Ведомый
  • в таблице value_map  указать, что записать в Ведомый при достижении значения Ведущим
  • в NC_WriteToSlave указать, что записать в Ведомый при потере связи с Ведущим 

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

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

 dofile2("masterslaveitems.lua")

 function main_custom()
  Library_Init ()
 end

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

 


Автоматически подтверждать ряд кодов неисправностей лифтовой станции

Задача

Для указанного перечня кодов неиспрановностей станции управления лифтом (СУЛ), подключенной через КСЛ-RS, необходимо автоматически квитировать сообщения об ошибке.

Например, при визуализации СУЛ УЛ примитив Лифтовая станция в SCADA отображает неисправность с кодом 22 - режим погрузки, как неисправность с красным восклицательным знаком.
Необходимо, чтобы программа сама квитировала данную ошибку, без реакции со стороны диспетчера.

Решение

Для решения указанной задачи, необходимо для одной или нескольких СУЛ указать перечень автоматически квитируемых кодов ошибок.

Следует отредактировать  таблицу lift_table в  файле .. \ scripts \ custom \ lift_table.lua 

 local lift_table = {
 ['УЛ'] = {
        [6]=0,
        [8]=0,
        [10]=0,
        [14]=0,
        [22]=0
            },
 ['ОТИС'] = {
        [11184]=0
            }
 }

В таблице lift_table мы указали, что для СУЛ:

  • УЛ, следует авто-квитировать коды 6, 8, 10, 14, 22
  • ОТИС - код 11184

В таблице lift_table может быть указана одна или несколько СУЛ.

Имя СУЛ должно совпадать с именем станции, отображаемом на примитиве Лифтовая станция.

Далее в файле  custom \ entry.lua, следует добавить строчки (1) - (3)

dofile2("lift_table.lua")   <--- (1)
dofile2("..\\built-in\\autoaccept_lift.lua")  <--- (2)
..
function main_custom()
...
CreateLiftTable ();            <--- (3)
...
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, логика созданного автомата управления должна работать.

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


Восстановление настроек частотника после обесточивания 

Задача

Необходимо повторно запустить частотник, управляемый дистанционно,  установив последнюю выставленную частоту.
Т.к. при кратковременном пропадании питания, частотник сбрасывает свои настройки.

-- Исходные данные
-- Частотник находящийся в состоянии  
-- Состояние  - включен
-- Авария - нет
-- Частота - 30
-- После обесточивания возвращается в состояние
-- Состояние  - выключен
-- Авария - нет
-- Частота - 0
-- Необходимо перевести частотник во включеное состояние с последней заданной частотой
-- Оператор может выключать установку, но при этом предполагается, что частота в 0 не уходит

Pch 01.png

Решение

Тэги частотника имеют следующий вид
DA.[localhost{188D08EC-72CB-425B-8EA8-EE2308736440}].IP/RS конвертер - moxa 4k.Modbus RTU - ЩПЧ1 В3-1.состояние ПЧ

Будет анализировать в скрипте последнюю составляющую тэгов

strState = "состояние ПЧ"        -- состояние установки
strError = "неисправность ПЧ"    -- признак ошибки
strF = "частота запись"          -- текущее значение частоты
strOnOff = "пуск/стоп"           -- управление установкой

local analize_signal = {
[strState] = 0,
[strError] = 1,
[strF] = 2
}

local pch_f = {};       -- частота > 0
local pch_f_zero = {};  -- частота = 0
local pch_state = {};   -- состояние
local pch_alarm = {};   -- признак ошибки

local function dowork (name, shortname)
  if pch_f_zero [name] ~= 1 then 
     return
  end
  local iState = pch_state [name]
  local iAlarm = pch_alarm [name]
  local iF = pch_f [name]
  if iF == nil or iState == nil or iAlarm == nil then
     -- Log ("","ext2") 
     return
  end
  if iF > 0.1 and  iState == 0 and iAlarm == 0 then
    -- Log ("","ext WORK")
     -- запишие частоту   
    local itemF, bResF = opc.da.tekon.GetItem(name .. strF)
    if (itemF~= nil) and bResF then
            local newData = base.Variant(iF); 
            itemF:AsyncWrite(newData);    
    end 
    -- включи установку     
    local itemControl, bRes = opc.da.tekon.GetItem(name .. strOnOff)
    if (itemControl~= nil) and bRes then
            local newState = base.Variant(1);
            itemControl:AsyncWrite(newState)    
    end 
  end
  -- Log ("","EXIT")
end

function PCh__OnDataChange  (topc_item, topc_itemdata)
    
    if topc_item == nil or topc_itemdata==nil or topc_itemdata.Data ==nil then        
        return
    end    
    
    local k = mysplit (topc_item.ItemID, ".")
    local b = analize_signal[k[#k]]
    
    if (b == nil) then 
     return
    end
    
    local i;
    local name = ""
    
    for i=1,#k-1 do
     name = name .. k[i] .. "."
    end
    
    if topc_itemdata.Quality ~= opc.da.tekon.ItemData.QUALITY_GOOD then
     pch_state [name] = nil
     pch_alarm [name] = nil
     return 
    end

    if pch_f_zero [name] == nil then
     pch_f_zero [name]  = 1
    end    
     
    -- Log ("", topc_item.ItemID .. "    " .. b)

    if b == 2 then 
      -- если значение не 0 просто записать его в кэш 
      if topc_itemdata.Data.Number > 0.1 then
        pch_f [name] = topc_itemdata.Data.Number
        pch_f_zero [name]  = 0
        return        
      end
      pch_f_zero [name] = 1;
      dowork (name, k[#k-1]) 
      return
    end 

    if b == 1 then 
      pch_alarm [name] = topc_itemdata.Data.Integer
      dowork (name, k[#k-1]) 
      return
    end
    
    if b == 0 then 
      pch_state [name] = topc_itemdata.Data.Integer
      dowork (name, k[#k-1]) 
      return
    end
   

end

function PCh_Init()
      -- Log ("","PCh_Init")
      opc.da.tekon.RegisterEventHandler( "OPC::DA::TEKON::OnDataChange", "PCh__OnDataChange")
      opc.da.tekon.RegisterEventHandler( "OPC::DA::TEKON::OnReadComplete", "PCh__OnDataChange")
end 

 


Увеличить мощность вентсистемы при сработке датчика СО

Задача

Автоматически не менее чем на N-секунд включить на полную мощность вентилятор при сработке датчика СО,
после снятия сигнала тревоги вернуть мощность вентилятора на прежнее значение

Решение

Скрипт доступен в папке ... \ build-in \ autostart_vent_upd.lua 
Скрипт можно использовать в версии 2.7.17 и выше

По-умолчанию скрипт не активен.

Для активации следует  в файле lvm \ custom \ entry.lua, следует добавить строку (1)  и блок  (2)

dofile2("..\\built-in\\autostart_vent_upd.lua")  <--- (1)
...
function main_custom()
...
GlobalVentControlTable.autocall_task_map = {     <--- (2) 
 ["Тег Аварийный сигнал 1"] =
{
[1] = "Тег канала управления мощностью 1"
},
["Тег Аварийный сигнал 1"] =
{
[1] = "Тег канала управления мощностью 2",
}
} 
GlobalVentControlTable.AutoVent_Init()   
...
end

Внимание! Важно!
Кодировка файла entry.lua должна быть ANSI Windows 1251. По необходимости воспользуйтесь программой Notepad++

Scripts lua win1251.PNG

Дополнительно вы также можете изменить следующие конфигурационные значения

  • на сколько секунда следует включить вентилятор на полную мощность (по умолчанию 15)
  • какое значение следует записать в вентилятор для включение полной мощности  (по умолчанию 100)

Для этого следует добавить строки (3)-(4) в entry.lua

dofile2("..\\built-in\\autostart_vent_upd.lua")
...
function main_custom()
...
 GlobalVentControlTable.MaxSecondsWait = 15     <--- (3)
 GlobalVentControlTable.SetAlarmVentValue = 100 <--- (4)
...
end

Пример заполненного файла lvm \ custom \ entry.lua

dofile2("..\\built-in\\autostart_vent_upd.lua")
function main_custom()
 GlobalVentControlTable.autocall_task_map = {
  ["DA.[localhost{188D08EC-72CB-425B-8EA8-EE2308736440}].КУН-IP8 - 0.DiscretChannel01"] =
  {
   [1] = "DA.[localhost{188D08EC-72CB-425B-8EA8-EE2308736440}].КУН-IP8 - 0.Modbus RTU - 0.Твключения"
  }
 }
 GlobalVentControlTable.AutoVent_Init()
end

Настройка SCADA

Скрипт использует служебную переменную VAR.ATimer  
Для корректной работы скрипта, следует отобразить на любом виде карты примитив цифровой индикатор, связанный с этой переменной.

Пример отображения примитивов:

  • Переменной (в свойстве Тег указываете самостоятельно VAR.ATimer 5)
  • Дискретного сигнала СО
  • Текстового поля с каналом управления вентилятором
Scripts lua vent2.PNG

 

Scripts lua vent1.PNG
 

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

 
Scripts lua vent3.PNG

Проинформировать, если в системе есть активный вызов

Задача

Зажечь LED-индикатор, если в системе присутствует хотя бы один активный вызов.

Решение

Воспользуемся скриптом, который анализирует состояние всех каналов ПГС, всех подключенных OPC-серверов.

Если скрипт опредяется, что в системе присуствует один или более активный канал ПГС, он записывает значение 1 в служебный Item локального ОРС-сервера: 

DA.[localhost{188D08EC-72CB-425B-8EA8-EE2308736440}].DAServerInfo.OutSignalInt1

Если активных вызовов нет, в Item будет записано значение 0.

Добавив на карту LED-индикатор связанный с этим же Item, мы получим оповещение о наличии активных вызовов.

Скрипт доступен в папке ... \ build-in \ voice.lua   (с версии 2.7.17)

По-умолчанию скрипт не активен.

Для активации следует  в файле  custom \ entry.lua, следует добавить строчки (1) - (3)

dofile2("..\\built-in\\voice.lua")  <--- (1)
..
function main_custom()
...
Voice_LocalServer = "127.0.0.1"    <--- (2)
Voice_Init ()                     <--- (3)
...
end

Во второй строке следует указать, с каким адресом у вас настроено подключение к локальному OPC-серверу, обычно это:

  • localhost
  • 127.0.0.1

Посмотреть настройку можно в  полe host в  файле .. \ settings \ opcclient.conf

...
<opc_da_server_list>
        <server host="127.0.0.1" catid="63D5F432-CFE4-11D1-B2C8-0060083BA1FB" clsid="188D08EC-72CB-425B-8EA8-EE2308736440" enabled="1">
            <authInfo/>
        </server>
...

Сохранить файл custom \ entry.lua  и запустить SCADA.

Переодически выводить звуковое уведомление, о наличии активного сигнала с указанным названием неисправности

Задача

Зажечь LED-индикатор, если в системе присутствует хотя бы один активный дискретный сигнал, название которого содержит указанное слово.

Решение

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

Если скрипт опредяется, что в системе присуствует один или более активный сигнал, название неиспраности  которого содержит указанное словосочетание (слово), он записывает значение 1 в служебный Item локального ОРС-сервера: 

DA.[localhost{188D08EC-72CB-425B-8EA8-EE2308736440}].DAServerInfo.OutSignalInt1

Если подходящих активных сигналов нет, в Item будет записано значение 0.

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

Скрипт доступен в папке ... \ build-in \ alert_sound.lua   (с версии 2.7.17)

По-умолчанию скрипт не активен.

Для активации следует  в файле  custom \ entry.lua, следует добавить строчки (1) - (3)

dofile2("..\\built-in\\alert_sound.lua")  <--- (1)
..
function main_custom()
...
Alert_LocalServer = "127.0.0.1"                  <--- (2)
Alert_Signal_Name = {"Затопление","затопление"}  <--- (3)
Alert_Signal_Second = 10                         <--- (4)
...
end

Во второй строке следует указать, с каким адресом у вас настроено подключение к локальному OPC-серверу, обычно это:

  • localhost
  • 127.0.0.1

Посмотреть настройку можно в  полe host в  файле .. \ settings \ opcclient.conf

...
<opc_da_server_list>
        <server host="127.0.0.1" catid="63D5F432-CFE4-11D1-B2C8-0060083BA1FB" clsid="188D08EC-72CB-425B-8EA8-EE2308736440" enabled="1">
            <authInfo/>
        </server>
...

В третье строке, следует перечислить слова (словосочетание), которые содержаться в названии анализируемого сигнала
(для скрипта "машина" и "Машина" - разные слова)

В четвертой, указать интервал вывода звукового уведомления. 

Сохранить файл custom \ entry.lua  и запустить SCADA.

В Scada следует отрисовать LED-индикатор, указав настройки:

  • Тэг -  DA.[localhost{188D08EC-72CB-425B-8EA8-EE2308736440}].DAServerInfo.OutSignalInt1
  • Звуковой файл - выбрать нужный
  • Журнал - Нет
  • Уведомления - Нет
  • Автоподтверждение - Да

Ограничения функционала:

  • анализируются только сигналы, которые перешли в активное состояние после запуска программы
  • анализируются только не квитированные диспетчером сигналы
  • если установить значение интервала Alert_Signal_Second меньше 5, могут не выводиться повторные уведомления об активных ПГС