Внимание! На данный момент система поддерживает работу со скриптами только на языке JavaScript, в связи с этим для понимания этой статьи необходимо обладать базовыми навыками работы с этим языком.
====== Скрипты в DevelSCADA ======
Для расширения базового функционала среды разработки DevelSCADA, система поддерживает возможность использования скриптов. Основным языком для разработки скриптов является JavaScript. Скрипты, в свою очередь поддерживают весь функционал языка JavaScript, дополняя его функциями работы с системой DevelSCADA.
Система поддерживает работу с двумя видами скриптов - **скрипты интерфейса** и **скрипты ПЛК**. Оба типа скриптов имеют идентичные интерфейсы для взаимодействия с системой, но при этом имеют разное предназначение.
**Скрипты интерфейса** предназначены в первую очередь для работы с элементами пользовательского интерфейса. Они могут быть созданы как в разделе "Скрипты" дерева проектов, так и в функциях обработки событий графических элементов интерфейса. Скрипты интерфейса работают на стороне клиента в его окне интерфейса, соответственно если несколько клиентов подключены к системе одновременно, у каждого клиента будут работать собственные экземпляры скриптов. Это необходимо учитывать при необходимости синхронизации визуального представления интерфейса, если предусмотрена одновременная работа несколькими пользователями. Так же скрипты интерфейса, привязанные с событиям графических элементов экрана, работают, соответственно, только на том экране, на котором они созданы. Так же и скрипты, созданные в разделе "Скрипты", запускаются каждый раз при переходе с экрана на экран. Если проект будет запущен, но при этом к нему не будет подключено ни одного клиента, никакие скрипты интерфейса работать не будут. Если необходимо постоянная работа скриптов, вне зависимости от работы клиентов и активного экрана, для этого необходимо использовать скрипты ПЛК.
**Скрипты ПЛК** запускаются сразу при старте проекта, и выполняются до тех пор, пока исполнение проекта не будет остановлено. В отличие от скриптов интерфейса, скрипты ПЛК не имеют функций прямого взаимодействия с элементами графического интерфейса, но при этом они работают постоянно, вне зависимости от того, что происходит в графическом интерфейсе. Скрипты ПЛК могут быть созданы только в разделе "Скрипты" дерева проекта.
====== Пример использования скриптов интерфейса ======
Выполнение скрипта интерфейса можно привязать к событию элемента интерфейса редактора экрана. Для примера сделаем скрипт, который будет выполняться при нажатии кнопки. Создадим в рабочей области экрана кнопку и выберем в свойствах элемента, в разделе "События", возле события "Нажатие", тип события "Скрипт".
{{ ::script01.png?nolink&400 |}}
После этого необходимо нажать кнопку редактирования скрипта.
{{ ::script02.png?nolink&400 |}}
Откроется окно текстового редактора скрипта.
{{ ::script03.png?nolink&400 |}}
Напишем код скрипта.
async function main(val) {
log('Hello world');
}
Запустим проект на исполнение. При нажатии на кнопку, в системный журнал будет выводиться текст сообщения скрипта.
{{ ::script04.png?nolink&400 |}}
Если необходимо создать функцию, которая будет вызываться многократно из разных мест графического интерфейса, удобнее всего ее создать в разделе "Скрипты" дерева проекта. Это можно сделать правым кликом из контекстного меню, либо по кнопке "Добавить" в самом разделе.
{{ ::script05.png?nolink&400 |}}
В появившемся окне необходимо выбрать "Скрипт интерфейса".
{{ ::script06.png?nolink&200 |}}
В разделе "Скрипты" появится созданный нами скрипт, и откроется окно текстового редактора скрипта.
{{ ::script07.png?nolink&600 |}}
Скрипты интерфейса могут иметь функцию **init**, которая всегда вызывается при загрузке любого экрана. В ней можно выполнять какие либо подготовительные операции, необходимые для работы остального кода. Добавим в данный скрипт собственную функцию вида:
export function myFunc() {
log('myFunc called');
}
//Внимание! Все функции, доступ к которым необходим не только из данного скрипта, обязательно должны иметь ключевое слово **export**.//
В результате скрипт должен иметь следующий вид:
{{ ::script08.png?nolink&400 |}}
Теперь вернемся к скрипту кнопки и отредактируем его код.
async function main(val) {
//log('Hello world');
let mySctipt = await ds.include('script_gui0');
mySctipt.myFunc();
}
Для доступа к функциям скрипта, предварительно нужно его подключить системной функцией **ds.include**, передав в качестве аргумента ей - имя скрипта. В результате в переменную **myScript** мы получим объект нашего скрипта, из которого в дальнейшем вызываем описанную в нем функцию.
Теперь при нажатии на кнопку, в системный журнал будет выведено сообщение из кода функции скрипта.
{{ ::script09.png?nolink&400 |}}
====== Пример использования скриптов ПЛК ======
Скрипты ПЛК создаются только в разделе "Скрипты" дерева проекта. Создается он аналогично скрипту интерфейса, с выбором соответствующего типа скрипта.
{{ ::script10.png?nolink&200 |}}
Для примера, создадим скрипт, который ежесекундно выводит в журнал сообщение с текущим временем.
async function init() {
while (true) {
log('Current date:', new Date());
await ds.sleep(1000);
}
}
Код скрипта разместим в функции **init**, которая будет вызываться при запуске проекта. После запуска проекта увидим сообщения в системном журнале, которые будут выводиться вне зависимости от того, какой экран проекта в данный момент открыт. Скрипт прекратит свое выполнение лишь после завершения выполнения проекта.
{{ ::script11.png?nolink&400 |}}
====== Взаимодействие скриптов интерфейса и ПЛК ======
Скрипты интерфейса могут вызывать функции скриптов ПЛК посредством вызова функции **callPlc**. При этом скрипты ПЛК не могут напрямую обращаться к функциям скриптов интерфейса. Это связано с тем, что контекстов исполнения скриптов интерфейса может быть несколько, или не быть ни одного, а контекст выполнения скриптов ПЛК всегда существует, и он всегда один. В связи с этим реализация доступа из скриптов ПЛК к функциям скриптов интерфейса не была реализована, чтобы не усложнять работу системы дополнительными проверками их доступности и синхронизацией. Если же необходимо из скриптов ПЛК влиять на работу скриптов интерфейса, то это можно легко реализовать, используя общие переменные устройства "Память".
====== Пример вызова функции скрипта ПЛК из скрипта интерфейса ======
Создадим в скаде код логики работы некоего устройства. К примеру сделаем таймер на 3 секунды, который будет выводить сообщение в журнал. Так же создадим функцию, которая будет управлять состоянием видимости сообщения. Так как этот код должен работать постоянно при работе проекта, его необходимо создать в скрипте ПЛК. Для этого создадим скрипт следующего вида:
let isActive = true;
async function init() {
while (true) {
if (isActive) log('hi');
await ds.sleep(3000);
}
}
function setActive(state) {
log('Set state:', state);
isActive = state;
}
Должен получиться проект следующего вида:
{{ ::script12.png?nolink&400 |}}
Далее создадим на экране две кнопки для включения и отключения статуса отображения сообщения посредством вызова функции [[ds.plccall|ds.plcCall]], которая вызывает функцию из скрипта ПЛК. Создадим в кнопках скрипты следующего содержания:
async function main(val) {
await ds.plcCall('script_plc0.setActive', [ true ]);
}
и
async function main(val) {
await ds.plcCall('script_plc0.setActive', [ false ]);
}
Запустим проект и понажимаем кнопки, в журнале будет видно как вызывается функция ПЛК **setActive**, изменяющая содержимое переменной **isActive**, и, соответственно, влияющая на работу таймера, выводящего сообщение.
{{ ::script13.png?nolink&300 |}}