Ekran SCADA projektowany w oparciu o skrypty .NET

110

Dowiedz się, jak rozszerzyć funkcjonalność oferowaną przez dowolny ekran SCADA wykorzystując własne skrypty .NET. Spis treści [Ukryj]

­

­

Skrypty dla ekranów SCADA w systemie ICONICS

W 64-bitowej implementacji oprogramowania SCADA GENESIS64 od firmy ICONICS wprowadzono nową metodę projektowania aplikacji SCADA. Zamiast opierania jej na rozbudowanym kodzie (pisanym w Visual Basic for Applications) udostępniono użytkownikowi obszerny zestaw konfigurowalnych komend.

Operacje takie jak zapisywanie wartości do zmiennych, ukrywanie obiektów, tworzenie menu można wykonać w całości bez programowania. Co więcej, obecność takich modułów w Workbench, jak np. GridWorX – do komunikacji z bazą danych, pozwala na łatwe uzyskanie łączności z zewnętrznymi źródłami zmiennych. Dane z większości modułów Workbench można natomiast zwizualizować za pomocą natywnych narzędzi w GraphWorX64. Tak więc operacje odczytu danych z baz SQL, czy śledzenia alarmów, a następnie ich wizualizacja może przebiec bez napisania jednej linii kodu. Wszystko opiera się na odpowiedniej konfiguracji określonych opcji.

Czasem jednak zdarza się, że końcowy klient wymaga pewnych specyficznych rozwiązań. Jeśli ich realizacja mogłaby być trudna, niemożliwa lub niepotrzebnie komplikowana z użyciem dostępnych komend, można posłużyć się własnymi skryptami.

Skrypty obsługujące ekran SCADA są projektowane bezpośrednio w programie GraphWorX, służącym do budowy graficznych interfejsów. Niniejszy wpis powstał, aby nieco przybliżyć technologię oraz sposób pisanie własnych funkcji wykonywanych podczas działania aplikacji.

Technologie systemu SCADA od ICONICS

GraphWorX64 wykorzystuje skrypty pisane w języku JScript.NET będącym odmianą Java Script. W przeciwieństwie do Java Script, bazuje on jednak na technologii .NET, będącej platformą programistyczną wydaną przez Microsoft Windows.

Tak więc język JScript.NET pozwala użytkownikowi na operowanie funkcjami przewidzianymi w ramach platformy .NET, jak i interakcję z każdym kodem pochodzącym z zewnętrznych bibliotek tej platformy.

Dodatkowo, program GraphWorX pozwala na eksport skryptów do plików z rozszerzeniami txt oraz js, jak również na ich import. Wszystkie operacje odbywają się w oknie Script Editor, zaprezentowanym w dalszej części wpisu.

Jako, że natywne narzędzia wizualizacyjne zawarte w GraphWorX same wykorzystują technologię .NET, również interakcja z nimi jest możliwa za pomocą skryptów. Do natywnych narzędzi należą między innymi te prezentujące dane o alarmach, informacje pochodzące z baz danych czy rysujące przebiegi czasowe sygnałów.

Przykład użycia skryptu przy budowie ekranu SCADA

Poniżej przedstawiony jest prosty przykład. Powoduje on przepisanie wartości z jednej zmiennej do drugiej. Cały proces następuje po przyciśnięciu określonego przez użytkownika przycisku. Wartości wyżej wspomnianych zmiennych są natomiast wyświetlane za pomocą dedykowanych okienek – ProcessPoint.

Pierwszą rzeczą, jaką należy dodać do interfejsu w GraphWorX są: dwa ProcessPoint’y (pokazujące wartość dwóch zmiennych) oraz przycisk. Następnie, do każdego z ProcessPoint’ów należy przypisać zmienną, której wartość wyświetlają. Ważną rzeczą jest nadanie każdemu z nich unikalnej dowolnej nazwy (pole „Name” pokazane na poniższym filmie).

Skrypty i SCADA – Prosty Projekt cz1

Kolejnym krokiem jest przyporządkowanie do przycisku odpowiedniej komendy w jego ustawieniach w zakładce „Dynamics”. W tym przypadku będzie to „Run Script”. Następnie, poprzez przejście do menu konfiguracji Zdarzeń (ikonka błyskawicy w zakładce „Dynamics”) możliwe jest otworzenie okna edycji skryptów i napisanie odpowiedniego kodu. Kod ten wykona się w tym przypadku po naciśnięciu tego przycisku za pomocą LPM.

Zawartość kodu zaprezentowana jest poniżej.

var FirstProcessPoint = ThisConfiguration.GetDynamicObjectByName("PPT_1");
var First_PP_Value =FirstProcessPoint.GetValueOfPrimaryDataSource();
var SecondProcessPoint = ThisConfiguration.GetDynamicObjectByName("PPT_2");
SecondProcessPoint.WriteValueToPrimaryDataSource(First_PP_Value);

Powyżej pogrubiono te nazwy, które użytkownik nadaje zmiennym w kodzie w dowolny sposób. Oczywiście zależności między nimi (ich wzajemne wywołania) nie mogą być już dowolne.

Do zmiennych: FirstProcessPoint oraz SecondProcessPoint (będących obiektami) przyporządkowano obiekty znajdujące się na ekranie SCADA, jakimi są dwa ProcessPoint’y. Do wykonania takiej operacji służy funkcja GetDynamicObjectByName, przyjmująca jako argument nazwę obiektu (nadaną w im w poprzednim kroku).

Następnie do zmiennej First_PP_Value przepisano wartość z pierwszego ProcessPoint’a. Stało się to za pomocą funkcji GetValueOfPrimaryDataSource() nie przyjmującej żadnych argumentów.

Na końcu programu, wartość tej zmiennej jest przekazywana do drugiego ProcessPoint’a, a więc do tag’u, który jest dla niego źródłem danych.

Skrypty i SCADA – Prosty Projekt cz2

Skrypty czy wbudowane komendy?

Jeśli pomyśli się, o rozbudowanych funkcjonalnościach platformy .NET oraz ilość dostępnych bibliotek, można dojść do wniosku, że użytkownik jest w stanie zbudować całą aplikację SCADA tylko za pomocą skryptów. Co więcej, jest to prawdziwe stwierdzenie.

Czy jednak w obliczu tak potężnego narzędzia, należy rezygnować z komend wbudowanych już w system SCADA?

Producent zaleca, aby używać własnych skryptów jedynie wtedy, gdy wykorzystanie wbudowanych funkcji jest albo zbyt skomplikowane, albo niemożliwe. Użytkownik nie powinien jednak wykonywać wszystkich operacji na podstawie napisanego przez siebie kodu.

Powodem może być przede wszystkim malejąca przejrzystość aplikacji tworzonej w taki sposób. W przypadku kilkunastu linii kodu, wychwycenie ewentualnego błędu jest stosunkowo proste. Jednak w przypadku rozbudowanych aplikacji SCADA, liczba wszystkich linii skryptów może wzrosnąć do kilkuset lub nawet kilku tysięcy.

Następujące fakty mówiące, że:

  • tekstowa prezentacja programu jest mniej czytelna dla człowieka od graficznej,
  • dany program można napisać na kilka sposobów (nawet w ramach tej samej platformy),

czynią aplikacje w pełni oparte na skryptach trudnymi do rozbudowy oraz modyfikacji. Szczególnie, gdy inżynier odpowiedzialny za poprawki nie jest tym, który tworzył pierwotny kod.

Dla porównania, można spojrzeć na poniższe wideo, które prezentuje, w jaki sposób wykonać analogiczny prosty projekt, w oparciu o komendy.

Skrypty i SCADA – Prosty Projekt za pomocą komendy

Na powyższym filmie widać, że skrypt wykorzystujący 4 funkcje może być zastąpiony przez jedną komendę, dla której należy uzupełnić 2 pola konfiguracyjne. Co więcej, w drugim rozwiązaniu (z komendą) nie jest wymagane nadanie unikalnej nazwy dla każdego z ProcessPoint’a (mimo, że to dobra praktyka).

Podsumowując, takie proste przykłady, jak ten przedstawiony w poprzedniej sekcji są dobre do nauki pisania skryptów. Jednak w przypadku projektowania całej aplikacji warto poważnie rozważyć używanie komend. Ich lista jest długa, konfiguracja wymaga jedynie uzupełnienia odpowiednich pól, a pomagają one uprościć projekt.

Bardziej przejrzysta aplikacja jest o wiele prostsza w rozbudowie oraz zarządzaniu.

Przykład projektu – współpraca aplikacji z plikami tekstowymi

Na koniec tego wpisu zaprezentowany zostanie jeszcze jeden przykład. Ukaże on w praktyce, jak funkcjonalności platformy .NET mogą usprawnić działanie aplikacji SCADA i sprawić, że będzie ona jeszcze bardziej uniwersalna. Czytając tą sekcję dowiesz się, jak zaprojektować ekran SCADA działający w oparciu o skrypty, by współpracował z plikami tekstowymi.

Czasem zdarza się, że inne systemy działające już w przedsiębiorstwie skonfigurowano tak, aby wymieniały informacje właśnie za pomocą pików z rozszerzeniem txt. Biorąc pod uwagę szerokie możliwości języka Java Script oraz platformy .NET, system SCADA od ICONICS może łatwo poradzić sobie z obsługą takich plików.

Założenia projketu

Przypuśćmy, że projektowany ekran SCADA powinien posiadać następującą funkcjonalność. Użytkownik powinien móc wprowadzać w pole tekstowe dowolny komentarz, a następnie, za pomocą odpowiedniego przycisku zapisywać go do pliku.

Co więcej, możliwy powinien być odczyt ostatniego komentarza z pliku, za pomocą tego samego pola tekstowego.

Oprócz samej treści komentarza, do pliku zapisywana jest również nazwa aktualnie zalogowanego użytkownika.

Dodanie potrzebnych elementów do ekranu SCADA

Pierwszy krok to umieszczenie na ekranie SCADA wszystkich potrzebnych elementów. Powinien on zawierać co najmniej wyżej wspomniane pole tekstowe oraz dwa przyciski – odczytu i zapisu do pliku.

Dlatego, że pierwszy etap umieszczenia przycisków jest taki sam jak w trzeciej sekcji tego wpisu, skupiono się na prezentacji ustawień pola tekstowego. Polem tym jest zwykły ProcessPoint z odpowiednio dobranymi ustawieniami

Projekt_2 – dodanie elementów do ekranu

Do powyższego ekranu dodano również ProcessPoint prezentujący nazwę aktualnie zalogowanego użytkownika. Nazwa ta jest przechowywana w jednej z lokalnych zmiennych GraphWorX (localsim::currentUser), pokazanej na poniższym zdjęciu.

Ekran SCADA i skrypty - nazwa użytkownika w zmiennej
Ekran SCADA i skrypty – nazwa użytkownika w zmiennej

Kod wykonywany po wybraniu przycisków

Przycisk pierwszy – zapis do pliku

Pierwszym krokiem jest utworzenie obiektu zapewniającego dostęp do sytemu plików na dysku komputera („FileSystemObject”).

var MyFileSystem = new ActiveXObject("Scripting.FileSystemObject");

Drugi krok to deklaracja zmiennej symbolizującej posiadany przez nas plik tekstowy.

var MyTextFile = MyFileSystem .OpenTextFile("Comments.txt", 8, false);

Pierwszy z argumentów powyższej funkcji to nazwa pliku (w ogólności – ścieżka względna razem z nazwą). Drugi (8) oznacza, że plik jest otwierany w trybie dopisywania do niego treści. Ostatni powoduje to, że plik nie jest tworzony w przypadku, gdy nasza aplikacja nie odnalazła go w podanej lokalizacji.

Kolejne linie kodu odnoszą się do pozyskania wartości z pól (ProcessPoint) przechowujących nazwę użytkownika i komentarz. (Porównaj z sekcją trzecią tego wpisu).

var CommentPointName = ThisConfiguration.GetDynamicObjectByName("CommentPoint"); 
var Comment = CommentPointName.GetValueOfPrimaryDataSource();
var UserPointName = ThisConfiguration.GetDynamicObjectByName("UserPoint");
var UserName = UserPointName.GetValueOfPrimaryDataSource();

Następnie tekst ten należy zapisać do pliku. Oprócz samych wartości komentarzy i nazw użytkowników można dołączyć tzw. słowa klucze opatrzone wyróżniającymi się znakami. Mogą one jednoznacznie wskazać miejsca w pliku, w których zaczynają się, bądź kończą interesujące nas informacje. Jest to szczególnie przydatne przy odczycie danych przez aplikację. W tym przypadku, potrzebny fragment kodu wygląda jak poniżej.

MyTextFile.Write("\n\n");      //podwójna nowa linia 
MyTextFile.Write("%UserName%: ");  //słowo klucz wskazujące na nazwę użytkownika 
MyTextFile.Write(UserName);   //nazwa użytkownika 
MyTextFile.Write("\n");      //nowa linia 
MyTextFile.Write("%Comment%: ");   //słowo klucz dla treści komentarza 
MyTextFile.Write(Comment);     //treść komentarza 

MyTextFile.Close();      //zamknięcie pliku

Tak, jak wcześniej, pogrubionym drukiem wyróżniono nazwy własne zmiennych i wartości, które nadaje użytkownik. Cały potrzebny kod znajduje się natomiast poniżej. Zawiera on dodatkowo funkcję warunkową „IF”, która sprawdza, czy podany plik istnieje. Jeśli nie, wyświetla ona okienko z odpowiednią informacją.

Jeśli dokument nie załadował się prawidłowo – odśwież stronę.

Drugi przycisk – odczyt ostatniego komentarza z pliku

Kod drugiego przycisku jest bardzo podobny do tego, omówionego w poprzedniej sekcji. Różni się on jedynie użyciem funkcji „ReadAll()”, „lastIndexOf(string_var)” oraz „Slice(pos1, pos2)”.

Pierwsza z nich odpowiada za odczyt całej zawartości pliku do zmiennej tekstowej. Druga zaś, wyszukuje i podaje pozycję ostatniego wystąpienia podciągu znaków w dłuższym ciągu. Szukany podciąg jest przekazywany jako parametr string_var. Ostatnia natomiast, wycina z ciągu znaków mniejszy ich ciąg, począwszy od pozycji pos1 do pos2 i zwraca jako osobną zmienną. W przypadku pominięcia drugiego z argumentów, wytnie ona dany ciąg znaków do końca.

Skrypt drugiego z przycisków najpierw wczytuje całą zawartość pliku do jednej zmiennej. Następnie szuka ostatniego wystąpienia ciągu „%Comment%:”. Gdy go odnajdzie, wycina ostatni komentarz ze zmiennej przechowującej całą zawartość pliku i przekazuje do odpowiedniego ProcessPoint’a.

Na podstawie poprzedniej sekcji i powyższych wyjaśnień, czytelnik powinien być w stanie zinterpretować poniższy kod.

Jeśli dokument nie załadował się prawidłowo – odśwież stronę.

Prezentacja rezultatów

Poniżej zamieszczono krótki film prezentujący efekt implementacji wyżej opisanego rozwiązania. Jest to oczywiście tylko przykład tego, w jaki sposób można wykorzystać skrypty przy projektowaniu aplikacji SCADA.

Prezentacja integracji z plikami tekstowymi

Podsumowanie

Jak widać, możliwość wdrożenia technologi .NET przy projektowaniu aplikacji SCADA otwiera bardzo szerokie spektrum możliwości przed integratorem. Ekran graficzny SCADA działający w oparciu o skrypty może posiadać takie same funkcjonalności, jakie oferowane są przez wyżej wymieniony framework.

Na koniec warto jeszcze raz przypomnieć, aby mimo dużej swobody płynącej z wykorzystania skryptów, stosować je tylko tam, gdzie jest to niezbędne. Oprogramowanie SCADA od ICONICS oferuje wiele wbudowanych funkcjonalności, które pomagają w uproszczeniu projektowania aplikacji.

Prawdziwie funkcjonalna i skalowalna aplikacja SCADA to taka, która oferuje wiele możliwości, ale też jest zaprojektowana w sposób uporządkowany i przejrzysty dla operatora.

Źródło: Elmark