Witamy

>> Pomoc dla użytkowników systemu Asix - wersji 7

www.asix.com.pl

Asix.Evo - Skrypty

Dok. Nr PLH7E003

Wersja: 2013-12-11


1 Podstawy użycia skryptów

W wielu aplikacjach zachodzi potrzeba zaimplementowania funkcjonalności, których nie można uzyskać używając tylko standardowych mechanizmów diagramów i obiektów wizualizacyjnych. Typowe przykłady takich funkcji to:

  • Wykonywanie nietypowych przeliczeń wartości zmiennych procesowych, szczególnie z użyciem wartości archiwalnych.

  • Zaprogramowanie nietypowych reakcji na zdarzenia zachodzące w kontrolowanym procesie.

  • Przekazywanie na zewnątrz aplikacji Asix.Evo wartości zmiennych i innych informacji o działaniu systemu.

  • Zaawansowane strategie wykrywania sytuacji alarmowych.

  • Pozyskiwanie danych z nietypowych źródeł danych, np. z baz danych firm trzecich.

  • Wykonywanie raportów.

  • Tworzenie specjalizowanych interfejsów użytkownika opartych o swobodnie tworzone okna.

W celu realizacji powyższych funkcji (i innych podobnych) Asix.Evo został wyposażony w moduł obsługi skryptów użytkownika. Asix.Evo zapewnia zintegrowane środowisko do tworzenia i uruchamiania skryptów.

Asix.Evo wykorzystuje możliwości stwarzane przez platformę .Net. W rzeczywistości skrypty aplikacyjne są w pełni kompilowanymi modułami .Net. Możliwe jest użycie języków programowania C# i Visual Basic. Skrypty użytkownika mogą korzystać z pełnego zestawu obiektów i funkcji platformy .Net. Dodatkowo środowisko wykonania skryptu jest rozszerzane o funkcje dostępu do elementów aplikacji Asix.Evo.

Skrypty użytkownika są uruchamiane w osobnych domenach aplikacji oraz we własnych wątkach. Skrypty i główny program są od siebie wzajemnie izolowane. Dzięki temu minimalizowane jest ryzyko, że błędne działanie skryptu spowoduje upadek całej aplikacji.


1.1 Utworzenie skryptu

Aby utworzyć nowy skrypt należy:

  • Otworzyć panel Eksplorator aplikacji.

  • Podwójnie kliknąć myszką na węźle Skrypty lub wykonać komendę Utwórz skrypt z menu kontekstowego węzła Skrypty. Spowoduje to otwarcie poniższego okienka:

Rys. Okno deklaracji nowego skryptu.

  • Określić język i nazwę skryptu oraz użyć przycisk Utwórz.

Efektem powyższych działań będzie wygenerowanie początkowego wzorca skryptu oraz otwarcie panelu edycji skryptów.


1.2 Edycja skryptów

Panel edycji skryptów jest podstawowym narzędziem służącym do pisania i testowego uruchamiania skryptów w aplikacji Asix.Evo. Dopuszczalne jest także użycie dowolnego innego edytora programistycznego – należy tylko zachować lokalizację pliku skryptu w katalogu definicyjnym aplikacji.

Rys. Panel edycji skryptów.

Edytor skryptów zapewnia kolorowanie kodu na podstawie składni, automatyczne formatowanie, natychmiastowe wykrywanie błędów, podpowiadanie i uzupełnianie nazw, rozwijanie składowych klas.

Niepoprawne fragmenty kodu są zaznaczane przez czerwone podkreślenie. Dodatkowo w dymku można wyświetlić skrócony opis błędu. Można też wykonać próbę pełnej kompilacji skryptu używając przycisk Sprawdź. Ewentualne błędy zostaną wyświetlone w tabelce komunikatów.

Jedną z najbardziej użytecznych funkcji edytora jest rozwijanie składowych i uzupełnianie nazw. Edytor sam rozpoznaje kontekst edycji i w odpowiednich momentach wyświetla okienko z proponowanymi alternatywami – mogą to być nazwy składowych klasy , nazwy zmiennych, elementy wyliczeniowe. Użytkownik może wymusić otwarcie okna podpowiedzi skrótem klawiaturowym Ctrl-spacja.

Panel edytora pozwala także na proste zarządzanie wykonaniem skryptu. Skrypt może zostać uruchomiony (z podaniem parametrów lub bez), można też wymusić zakończenie jego pracy.


1.3 Metody uruchamiania skryptów

Skrypty w aplikacji Asix.Evo uruchamiane są zawsze przy pomocy akcji operatorskiej Script.

Script(nazwa , parametr1, parametr2, ...)

W treści wywołania należy podać nazwę skryptu oraz odpowiednią liczbę parametrów uruchomienia. Akcję Script można używać wszędzie tam, gdzie dopuszczalne jest użycie akcji operatorskiej.

Można wyróżnić dwie główne kategorie skryptów: skrypty interakcyjne uruchamiane w wyniku działań operatora oraz skrypty autonomiczne, działające w tle aplikacji, wykonujące funkcje nie związane bezpośrednio z działaniami operatora.


1.3.1 Skrypty interakcyjne

W przypadku skryptów interakcyjnych akcja operatorska Script jest używana jako akcja podpięta do zdarzenia obiektu wizualizacyjnego lub jako akcja menu użytkownika.

Rys. Przykład akcji operatorskiej w przypadku skryptów interakcyjnych.

Powyższy przykład pokazuje definicję elementu menu użytkownika, którego użycie będzie powodowało wykonanie skryptu StartAll.

Rys. Definicja elementu menu użytkownika, którego użycie będzie powodowało wykonanie skryptu StartAll.

Kolejny przykład pokazuje identyczną akcję, ale tym razem użytą w obsłudze zdarzenia wciśnięcia przycisku w obiekcie klasy Przycisk.


1.3.2 Skrypty autonomiczne

Skrypty autonomiczne uruchamiane są z reguły poprzez mechanizm terminarza. Najczęściej skrypty tego typu używane są w elementach terminarza, których tryb wykonania jest równy Jednokrotnie przy starcie aplikacji. W tym trybie skrypt jest uruchomiony przy starcie i kontynuuje swoją pracę aż do zakończenia aplikacji. Możliwe jest też użycie trybu okresowego uruchamiania lub uruchamiania przy zajściu określonego zdarzenia. W tych trybach skrypt jest uruchamiany wielokrotnie – powinien wykonać swoje zadanie, a następnie się zakończyć.

Uwaga:

Funkcjonalność wykonywania pewnych funkcji okresowo lub w reakcji na zajście określonego zdarzenia, można zrealizować w łatwy sposób wewnątrz skryptu uruchamianego jednokrotnie. Taka technika jest bardziej efektywna – nie wymaga kosztownego procesu każdorazowego uruchomienia skryptu.

Rys. Terminarz - tryby uruchomienia skryptu OptimizeSpeed.

Powyższy przykład pokazuje różne tryby uruchomienia skryptu OptimizeSpeed.


1.4 Zarządzanie aktywnymi skryptami

Interaktywne zarządzanie pracującymi skryptami jest możliwe za pośrednictwem panelu diagnostycznego skryptów. Panel Aktywne skrypty otwierany jest poprzez wybranie węzła Diagnostyka/Aktywne skrypty w panelu Eksplorator aplikacji lub w trybie wykonania aplikacji za pośrednictwem panelu kontrolnego.

Rys. Panel aktywnych skryptów.

Okno aktywnych skryptów pozwala obserwować, zamykać i restartować wszystkie aktualnie pracujące skrypty. Umożliwia również uruchamianie nowych skryptów.

Alternatywne metody kontroli pracy skryptów oparte są na wykorzystaniu akcji operatorskich ScriptRestart i ScriptClose oraz funkcji IsScriptWorking. Skrypt może wymusić też własny restart, stosując metodę RestartScript.


1.5 Struktura kodu skryptu

Skrypty Asix.Evo mogą być tworzone w obiektowych językach C# oraz Visual Basic. W momencie utworzenia skryptu jest generowany szkielet jego kodu:

C#

using System;
using System.Windows.Forms;
using Askom.AsixEvo.Scripting;

public class SkryptT1 : IScript
{
   public bool Initialize(string[] aParameters, IApplication aApplication)
   {
      return true;
   }

   public void FinalizeScript()
   {
   }
}

VB

Imports System;
Imports System.Windows.Forms;

Imports Askom.AsixEvo.Scripting;

Public Class SkryptT2
    Implements IScript

    Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As IApplication) As Boolean Implements IScript.Initialize

        Return True
    End Function

    Public Sub FinalizeScript() Implements IScript.FinalizeScript

    End Sub

End Class

Główna klasa skryptu musi implementować interfejs IScript zdefiniowany w przestrzeni Askom.AsixEvo.Scripting.

C#

public interface IScript
{
   bool Initialize(string[] aParameters, IApplication aAscent);
   void FinalizeScript();
}

VB

Public Interface IScript
    Function Initialize(ByVal aParameters() As String, ByVal aApplication As IApplication) As Boolean
    Sub FinalizeScript()
End Interface

Funkcja Initialize, to główna funkcja skryptu wywoływana w momencie jego uruchomienia. Funkcja otrzymuje na wejściu dwa parametry:

  • aParameters – jest to tablica zawierająca wszystkie parametry przekazane podczas uruchomienia skryptu

  • aApplication – przekazuje odwołanie do interfejsu IApplication, który pozwala na dostęp do stanu wykonywanej aplikacji. Jest to podstawowy mechanizm współpracy skryptu ze środowiskiem aplikacji Asix.Evo.

Wartość zwracana przez funkcję Initialize określa, czy skrypt zakończył pracę. Wartość true oznacza, że skrypt zrealizował wszystkie swoje funkcje i należy go rozładować. Jest to typowe działanie tzw. skryptów jednorazowych. Skrypty rezydentne powinny zwrócić wartość false. Skrypt pozostanie załadowany w pamięci i będzie mógł kontynuować swoją działalność.

Funkcja FinalizeScript jest wywoływana bezpośrednio przed zakończeniem pracy skryptu. Można w niej wykonać operacje wymagane do poprawnego zakończenia pracy skryptu, np. zwolnienie użytych zasobów systemowych, zamknięcie połączeń z bazą danych itp.


2.1 Skrypty jednorazowe

Skrypty jednorazowe uruchamiane są najczęściej w sposób interaktywny przez operatora lub okresowo przy pomocy terminarza. Skrypt jednorazowy działa z reguły krótki czas. Całość jego funkcji znajduje się wewnątrz metody Initialize (lub innych metodach wywoływanych przez metodę Initialize). W przypadku skryptu jednorazowego metoda Initialize musi zwracać wartość true.

Przykład pokazuje skrypt, którego zadaniem jest rejestrowanie w pliku tekstowym obecności operatora. Operator ma za zadanie okresowo uruchamiać skrypt (np. poprzez użycie odpowiednio skonfigurowanego obiektu Przycisk), a każdorazowe uruchomienie spowoduje zapis komunikatu w pliku rejestru.

C#

using System;
using System.Windows.Forms;
using Askom.AsixEvo.Scripting;
using System.IO;

public class Single : IScript
{
   public bool Initialize(string[] aParameters, IApplication aApplication)
   {
      StreamWriter writer = new StreamWriter(

         Path.Combine(aApplication.ApplicationWorkingDirectory, "logs\\rejestr.txt"), true,

         System.Text.ASCIIEncoding.GetEncoding(1250));
      String msg = String.Format("{0} Zgłoszenie obecności: operator = {1}, stanowisko = {2}",

         DateTime.Now, aApplication.CurrentUserName, aApplication.CurrentStationName);
      writer.WriteLine(msg);
      writer.Close();

      aApplication.ReportMessage(EvoMessageType.Info, "Zgłoszenie operatora zarejestrowane");

      return true;
   }

   public void FinalizeScript()
   {

   }
}

VB

Imports System
Imports System.Windows.Forms
Imports Askom.AsixEvo.Scripting
Imports System.IO

Public Class SingleVB
    Implements IScript

    Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

        IApplication) As Boolean Implements IScript.Initialize

        Dim writer As StreamWriter
        writer = New StreamWriter(Path.Combine(aApplication.ApplicationWorkingDirectory,

            "logs\\rejestr.txt"), True, System.Text.ASCIIEncoding.GetEncoding(1250))

        Dim msg As String
        msg = String.Format("{0} Zgłoszenie obecności: operator = {1}, stanowisko = {2}", _
            Date.Now, aApplication.CurrentUserName, aApplication.CurrentStationName)
        writer.WriteLine(msg)
        writer.Close()

        aApplication.ReportMessage(EvoMessageType.Info, "Zgłoszenie operatora zarejestrowane")

        Return True

    End Function

    Public Sub FinalizeScript() Implements IScript.FinalizeScript

    End Sub

End Class

Całość kodu znajduje się w funkcji Initialize. Na początku tworzony jest obiekt klasy StreamWriter. W jego konstruktorze przekazywana jest nazwa pliku, wybierana opcja dopisywania do pliku oraz wybierany sposób kodowania tekstów (domyślnie stosowane byłoby kodowanie UTF8). Nazwa pliku tworzona jest na podstawie nazwy katalogu roboczego aplikacji zwracanego przez właściwość ApplicationWorkingDirectory. Następnie tworzony i zapisywany jest tekst komunikatu, w którego treści umieszczana jest nazwa aktualnie zalogowanego użytkownika CurrentUserName oraz nazwa stanowiska CurrentStationName. Na końcu funkcja Initialize zwraca wartość true informującą o zakończeniu działania skryptu.

Wywołanie funkcji ReportMessage nie jest niezbędne. Dobrym zwyczajem jest jednak rejestrowanie w standardowym logu komunikatów informujących o pracy skryptu oraz ewentualnych błędach wykonania.


2.2 Skrypty rezydentne

Skrypty rezydentne charakteryzują się tym, że po uruchomieniu, pozostają w trybie działania aż do momentu zakończenia pracy aplikacji. Z reguły uruchamiane są przy starcie aplikacji przy pomocy mechanizmu terminarza.

W skryptach rezydentnych metoda Initialize służy z reguły jedynie do inicjacji skryptu, a główna funkcjonalność jest realizowana w wykreowanych wątkach lub zadeklarowanych funkcjach zwrotnych. W przypadku skryptu rezydentnego metoda Initialize musi zwracać wartość false.

Istnieją różne wzorce programowe służące do tworzenia skryptów rezydentnych, opisane w następnych rozdziałach.


2.2.1 Pętle w metodzie Initialize

Metoda niekończącej się pętli w metodzie Initialize, to najprostsza konstrukcja mająca wiele wspólnego ze skryptami jednorazowymi. Główna funkcjonalność realizowana jest w metodzie Initialize . Działanie metody jednak nigdy się nie kończy (a dokładnie zostanie automatycznie zakończone w momencie końca pracy aplikacji). Jest to jedyny przypadek, gdzie z oczywistych powodów, wartość zwracana przez metodę Initialize nie jest istotna.

C#

using System;
using System.Windows.Forms;
using Askom.AsixEvo.Scripting;

public class Loop : IScript
{
   IApplication application;

   public bool Initialize(string[] aParameters, IApplication aApplication)
   {
      application = aApplication;
      while (true)
      {
         DoTask();
         aApplication.Sleep(TimeSpan.FromSeconds(1));
      }

      return true;
   }

   public void FinalizeScript()
   {

   }

   void DoTask()
   {
      application.ReportMessage(EvoMessageType.Info, "Wykonano cykl pracy skryptu");
   }
}

VB

Imports System
Imports System.Windows.Forms
Imports Askom.AsixEvo.Scripting

Public Class LoopVB
    Implements IScript

    Dim application As IApplication
    Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

        IApplication) As Boolean Implements IScript.Initialize

        application = aApplication
        While (True)

            DoTask()
            aApplication.Sleep(TimeSpan.FromSeconds(1))

        End While

        Return True

    End Function

    Public Sub FinalizeScript() Implements IScript.FinalizeScript

    End Sub

    Sub DoTask()

        application.ReportMessage(EvoMessageType.Info, "Wykonano cykl pracy skryptu")

    End Sub

End Class

Główna funkcjonalność skryptu realizowana jest w metodzie DoTask. W metodzie Initialize znajduje się nieskończona pętla typu While, w której metoda DoTask jest cyklicznie wywoływana. Pomiędzy kolejnymi wywołaniami następuje 1-sekundowe zawieszenie pracy cyklu. Użyta metoda Sleep interfejsu IApplication jest zalecaną metodą zawieszania działania skryptu na określony okres czasu.


2.2.2 Wykorzystanie funkcji RegisterTimeEvent

Metoda funkcji RegisterTimeEvent interfejsu IApplication polega na zadeklarowaniu funkcji zwrotnej, które będzie okresowo wykonywana. Funkcja RegisterTimeEvent pozwala na bardzo szczegółowe określenie okresu i momentów wykonywania funkcji zwrotnej.

C#

using System;
using System.Windows.Forms;
using Askom.AsixEvo.Scripting;

public class Timer : IScript
{
   IApplication application;
   public bool Initialize(string[] aParameters, IApplication aApplication)
   {
      application = aApplication;
      application.RegisterTimeEvent(Report1Hour, TimeSpan.FromHours(1),

                                    TimeSpan.FromMinutes(15));
       return false;
   }

   public void FinalizeScript()
   {

   }

   void Report1Hour()
   {
      application.ReportMessage(EvoMessageType.Info, "Wykonanie raportu o godzinie " +

                                DateTime.Now);
   }
}

VB

Imports System
Imports System.Windows.Forms
Imports Askom.AsixEvo.Scripting

Public Class TimerVB
    Implements IScript

    Dim application As IApplication
    Public Function Initialize(ByVal aParameters() As String, ByVal aApplication _

        As IApplication) As Boolean Implements IScript.Initialize

        application = aApplication
        application.RegisterTimeEvent(AddressOf Report1Hour, TimeSpan.FromHours(1), _

                                      TimeSpan.FromMinutes(15))
        Return False

    End Function

    Public Sub FinalizeScript() Implements IScript.FinalizeScript

    End Sub

    Sub Report1Hour()

        application.ReportMessage(EvoMessageType.Info, "Wykonanie raportu o godzinie " _

                                  & DateTime.Now)
    End Sub

End Class

W metodzie Initialize rejestrowana jest funkcja zwrotna Report1Hour. Zwrócenie wartości false powoduje, że skrypt pozostanie załadowany w pamięci.

Drugi parametr metody RegisterTimeEvent określa okres czasu pomiędzy kolejnymi wywołaniami funkcji zwrotnej, a parametr trzeci przesunięcie chwili początkowej. Metoda Report1Hour będzie wywoływana co 1 godzinę, 15 minut po każdej pełnej godzinie.


2.2.3 Tworzenie wątków

W przypadku stosowania metody wielu wątków wykorzystywana jest metoda CreateThread interfejsu IApplication. Możliwe jest utworzenie wielu wątków, które będą wykonywane niezależnie. Sposób działania wątków oraz ich wzajemna synchronizacja jest całkowicie dowolne – należy stosować metody synchronizacji udostępniane przez platformę .NET.

C#

using System;
using System.Windows.Forms;
using Askom.AsixEvo.Scripting;

public class ThreadDemo : IScript
{
   IApplication application;
   public bool Initialize(string[] aParameters, IApplication aApplication)
   {
      application = aApplication;

      System.Threading.Thread t1 = aApplication.CreateThread(ThreadFun);
      t1.Start();

      return false;
   }

   public void FinalizeScript()
   {

   }

   void ThreadFun()
   {
      while (true)
      {
         application.ReportMessage(EvoMessageType.Info, "Wykonano cykl pracy skryptu");
         application.Sleep(TimeSpan.FromSeconds(1));
      }
   }
}

VB

Imports System
Imports System.Windows.Forms
Imports Askom.AsixEvo.Scripting

Public Class ThreadDemoVB
    Implements IScript

    Dim application As IApplication
    Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

        IApplication) As Boolean Implements IScript.Initialize

        application = aApplication
        Dim t As System.Threading.Thread
        t = aApplication.CreateThread(AddressOf ThreadFun)
        t.Start()
        Return False

    End Function

    Public Sub FinalizeScript() Implements IScript.FinalizeScript

    End Sub

    Sub ThreadFun()

        While True
            application.ReportMessage(Askom.MessageLogging.MessageType.Warning, _

                                      "Wykonano cykl pracy skryptu")
            application.Sleep(TimeSpan.FromSeconds(1))
        End While

    End Sub

End Class

W metodzie Initialize tworzony jest nowy wątek roboczy przy pomocy metody CreateThread. Jako funkcje wątku podano metodę ThreadFun. Po utworzeniu nowy wątek jest uruchamiany. Zwrócenie wartości false powoduje, że skrypt pozostanie załadowany w pamięci i wątek będzie mógł kontynuować pracę.

Uruchomienie wątku powoduje wywołanie metody ThreadFun. Główna funkcjonalność skryptu realizowana jest wewnątrz nieskończonej pętli typu While. Pomiędzy kolejnymi cyklami pracy następuje 1-sekundowa przerwa. Należy unikać tworzenia wątków, które działają bez żadnych przerw, ponieważ powoduje to nadmierne obciążenie pracy procesora.

Metodę niezależnych wątków należy stosować wtedy, gdy istnieje konieczność uruchomienia więcej niż jednego wątku. Pokazany przykład można byłoby prościej zaimplementować, stosując metodę nieskończonej pętli w metodzie Initialize.


2.2.4 Monitorowanie zmian zmiennej procesowej

Metoda tworzenia skryptów rezydentnych synchronizowanych zmianami wartości bieżącej zmiennej procesowej, polega na zadeklarowaniu funkcji zwrotnej, która będzie wywoływana przy każdej zmianie stanu zmiennej. Do rejestracji funkcji zwrotnej wykorzystywana jest metoda RegisterStateEvent interfejsu IVariable. Przykładowy kod znajduje się w rozdziale dotyczącym odczytu wartości bieżących zmiennych procesowych (patrz: 2.4. Odczyt wartości bieżących zmiennych procesowych).


2.2.5 Monitorowanie stanu alarmów

Metoda tworzenia skryptów rezydentnych synchronizowanych zmianami stanu wybranego alarmu, polega na zadeklarowaniu funkcji zwrotnej, która będzie wywoływana przy każdej zmianie stanu alarmu. Do rejestracji funkcji zwrotnej wykorzystywana jest metoda RegisterStateEvent interfejsu IAlarm. Przykładowy kod znajduje się w rozdziale dotyczącym kontrolowania stanu alarmów (patrz: 2.9. Kontrola stanu alarmów).


2.3 Odczyt parametrów uruchomienia skryptu

W momencie uruchomienia skryptu do funkcji Initialize przekazywana jest tablica aParameters, z której można odczytać wartości wszystkich parametrów wywołania. Mechanizm parametrów pozwala na pisanie uniwersalnych skryptów, których szczegóły działania zależą od sposobu wywołania. Typowe przykłady, to przekazanie nazwy zmiennej procesowej, identyfikatora alarmu, nazwy pliku itd..

Istnieją dwie metody odczytu parametrów wywołania. Pierwsza wykorzystuje przeglądanie wszystkich elementów tablicy parametrów. W drugiej stosowany jest dostęp do argumentu poprzez podanie jego numeru kolejnego.

C#

using System;
using System.Windows.Forms;
using Askom.AsixEvo.Scripting;

public class Argumenty : IScript
{
   public bool Initialize(string[] aParameters, IApplication aApplication)
   {
      int i = 0;
      if (aParameters != null)
      {
         foreach (string p in aParameters)
            aApplication.ReportMessage(EvoMessageType.Info,

                                       String.Format("Parametr {0} = {1}", ++i, p));
      }

      return true;
   }

   public void FinalizeScript()
   {

   }
}

VB

Imports System
Imports System.Windows.Forms
Imports Askom.AsixEvo.Scripting

Public Class ArgumentyVB
    Implements IScript

    Public Function Initialize(ByVal aParameters() As String, ByVal aApplication _

        As IApplication) As Boolean Implements IScript.Initialize

        Dim i As Integer
        i = 0

        If (Not aParameters Is Nothing) Then
            For Each p As String In aParameters
                i += 1
                aApplication.ReportMessage(EvoMessageType.Info, _

                                           String.Format("Parametr {0} = {1}", i, p))
            Next p
        End If

        Return True

    End Function

    Public Sub FinalizeScript() Implements IScript.FinalizeScript

    End Sub

End Class

Powyższy kod pokazuje sposób iteracji po wszystkich elementach tablicy parametrów aParameters.

C#

using System;
using System.Windows.Forms;
using Askom.AsixEvo.Scripting;

public class Argumenty : IScript
{
   public bool Initialize(string[] aParameters, IApplication aApplication)
   {

      if (aParameters == null || aParameters.Length < 2)
         aApplication.ReportMessage(EvoMessageType.Info, "Zbyt mało parametrów");
      else
      {
         aApplication.ReportMessage(EvoMessageType.Info, "Parametr 1 = " + aParameters[0]);
         aApplication.ReportMessage(EvoMessageType.Info, "Parametr 2 = " + aParameters[1]);
      }

      return true;
   }

   public void FinalizeScript()
   {

   }
}

VB

Imports System
Imports System.Windows.Forms
Imports Askom.AsixEvo.Scripting

Public Class ArgumentyVB
    Implements IScript

    Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

        IApplication) As Boolean Implements IScript.Initialize

        If (aParameters Is Nothing) Then
            aApplication.ReportMessage(EvoMessageType.Info, "Brak parametrów")
        ElseIf (aParameters.Length < 2) Then
            aApplication.ReportMessage(EvoMessageType.Info, "Zbyt mało parametrów")
        Else
            aApplication.ReportMessage(EvoMessageType.Info, "Parametr 1 = " + aParameters(0))
            aApplication.ReportMessage(EvoMessageType.Info, "Parametr 2 = " + aParameters(1))
        End If

        Return True

    End Function

    Public Sub FinalizeScript() Implements IScript.FinalizeScript

    End Sub

End Class

Powyższy kod pokazuje sposób odczytu parametru przez podanie indeksu elementu w tablicy aParameters. Przed próbą odczytu należy koniecznie sprawdzić, czy do skryptu przekazano odpowiednią liczbę parametrów.


2.4 Odczyt wartości bieżących zmiennych procesowych

Odczyt wartości bieżących zmiennych możliwy jest dwoma metodami. Pierwsza z nich to użycie metody GetVariableValue interfejsu IApplication. Druga metoda to odczyt za pomocą obiektów interfejsu IVariable. Obiekt IVariable dla wybranej zmiennej można uzyskać za pośrednictwem funkcji GetVariable interfejsu IApplication.

Metoda GertVariableValue powinna być wykorzystywana tylko w najprostszych skryptach, w których wartość zmiennej jest odczytywana jednokrotnie. W innych przypadkach należy stosować metodę z obiektem IVariable ze względu na jej większą wydajność.

Przykład pokazuje najprostszy przypadek, w którym bieżąca wartość zmiennej jest jednokrotnie zapisywana do logu komunikatów.

C#

using System;
using System.Windows.Forms;
using Askom.AsixEvo.Scripting;

public class CurrValues : IScript
{
public bool Initialize(string[] aParameters, IApplication aApplication)
{
VariableState v = aApplication.GetVariableValue(aParameters[0], false);
if (v == null)

aApplication.ReportMessage(EvoMessageType.Error,
string.Format("Zmienna {0} nie jest zdefiniowana", aParameters[0])); else
{
if (v.IsGood)
{
aApplication.ReportMessage(EvoMessageType.Error,
string.Format("Wartość zmiennej {0}, Stempel czasu: {1}",
v.Value, v.TimeStamp));
}
else
aApplication.ReportMessage(EvoMessageType.Error,
string.Format("Niepoprawny status wartości {0} ", v.Status));
}

return true;
}

public void FinalizeScript()
{
}
}

VB

Imports System
Imports System.Windows.Forms
Imports Askom.AsixEvo.Scripting

Public Class CurrValuesVB
Implements IScript

Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

IApplication) As Boolean Implements IScript.Initialize

Dim v As VariableState
v = aApplication.GetVariableValue(aParameters(0), False)
If v Is Nothing Then
aApplication.ReportMessage(EvoMessageType.Error, _
String.Format("Zmienna {0} nie jest zdefiniowana", aParameters(0)))
Else
If (v.IsGood) Then
aApplication.ReportMessage(EvoMessageType.Error, _
String.Format("Wartość zmiennej {0}, Stempel czasu: {1}", _
v.Value, v.TimeStamp))
Else
aApplication.ReportMessage(EvoMessageType.Error, _
String.Format("Niepoprawny status wartości {0} ", v.Status))
End If
End If

Return True

End Function

Public Sub FinalizeScript() Implements IScript.FinalizeScript

End Sub

End Class

Pierwszy wariant skryptu używa zalecaną w tym przypadku funkcję GetVariableValue. Po uzyskaniu poprawnego obiektu VariableState dla zmiennej o nazwie przekazanej w parametrach wywołania, wartość zmiennej jest zapisywana do logu. Aktualna wartość, status i stempel czasu jest dostępna poprzez właściwości obiektu VariableState. Należy zwrócić uwagę na sposób weryfikacji poprawności zmiennej poprzez wywołanie metody IsGood.

C#

using System;
using System.Windows.Forms;
using Askom.AsixEvo.Scripting;

public class CurrValues : IScript
{
public bool Initialize(string[] aParameters, IApplication aApplication)
{
IVariable v = aApplication.GetVariable(aParameters[0], false);
if (v == null)

aApplication.ReportMessage(EvoMessageType.Error,
string.Format("Zmienna {0} nie jest zdefiniowana", aParameters[0])); else
{
if (v.VariableState.IsGood)
{
aApplication.ReportMessage(EvoMessageType.Error,
string.Format("Wartość zmiennej {0}, Stempel czasu: {1}",
v.VariableState.Value, v.VariableState.TimeStamp));
}
else
aApplication.ReportMessage(EvoMessageType.Error,
string.Format("Niepoprawny status wartości {0} ", v.VariableState.Status));

v.Dispose();
}

return true;
}

public void FinalizeScript()
{
}
}

VB

Imports System
Imports System.Windows.Forms
Imports Askom.AsixEvo.Scripting

Public Class CurrValuesVB
Implements IScript

Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

IApplication) As Boolean Implements IScript.Initialize

Dim v As IVariable
v = aApplication.GetVariable(aParameters(0), False)
If v Is Nothing Then
aApplication.ReportMessage(EvoMessageType.Error, _
String.Format("Zmienna {0} nie jest zdefiniowana", aParameters(0)))
Else
If (v.VariableState.IsGood) Then
aApplication.ReportMessage(EvoMessageType.Error, _
String.Format("Wartość zmiennej {0}, Stempel czasu: {1}", _
v.VariableState.Value, v.VariableState.TimeStamp))
Else
aApplication.ReportMessage(EvoMessageType.Error, _
String.Format("Niepoprawny status wartości {0} ", v.VariableState.Status))
End If
v.Dispose()
End If

Return True

End Function

Public Sub FinalizeScript() Implements IScript.FinalizeScript

End Sub

End Class

W drugim wariancie, dla celów porównawczych użyty jest obiekt klasy IVariable. Po uzyskaniu poprawnego obiektu IVariable dla zmiennej o nazwie przekazanej w parametrach wywołania, wartość zmiennej jest zapisywana do logu. Aktualna wartość, status i stempel czasu jest dostępna poprzez właściwość VariableState obiektu zmiennej. Należy zwrócić uwagę na sposób weryfikacji poprawności zmiennej poprzez wywołanie metody IsGood. Po wykonaniu zapisu informacji do logu, obiekt zmiennej jest zwalniany poprzez wywołnie metody Dispose.

Wartość zmiennej uzyskana w poprzednich przykładach pochodzi z ostatniego planowego odświeżenia zmiennej. Przy rzadko odświeżanych zmiennych może być ona przestarzała. Jeżeli skrypt wymaga działania na jak najbardziej aktualnej wartości, należy ustawić drugi parametr funkcji GetVariableValue na true lub użyć funkcję Read interfejsu IVariable.

C#

using System;
using System.Windows.Forms;
using Askom.AsixEvo.Scripting;

public class CurrValuesRead : IScript
{
public bool Initialize(string[] aParameters, IApplication aApplication)
{
IVariable v = aApplication.GetVariable(aParameters[0], false);
if (v == null)
{
aApplication.ReportMessage(EvoMessageType.Error,
string.Format("Zmienna {0} nie jest zdefiniowana", aParameters[0]));
}
else
{
VariableState vValue = v.Read();
if (vValue.IsGood)
{
aApplication.ReportMessage(EvoMessageType.Error,
string.Format("Wartość zmiennej {0}, Stempel czasu: {1}",
vValue.Value, vValue.TimeStamp));
}
else
aApplication.ReportMessage(EvoMessageType.Error,
string.Format("Niepoprawny status wartości {0} ", vValue.Status));

v.Dispose();
}
return true;
}

public void FinalizeScript()
{
}
}

VB

Imports System
Imports System.Windows.Forms
Imports Askom.AsixEvo.Scripting

Public Class CurrValuesReadVB
Implements IScript

Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

IApplication) As Boolean Implements IScript.Initialize

Dim v As IVariable
v = aApplication.GetVariable(aParameters(0), False)
If v Is Nothing Then
aApplication.ReportMessage(EvoMessageType.Error, _
String.Format("Zmienna {0} nie jest zdefiniowana", aParameters(0)))
Else
Dim vValue As VariableState
vValue = v.Read()
If (vValue.IsGood) Then
aApplication.ReportMessage(EvoMessageType.Error, _
String.Format("Wartość zmiennej {0}, Stempel czasu: {1}", _
vValue.Value, vValue.TimeStamp))
Else
aApplication.ReportMessage(EvoMessageType.Error, _
String.Format("Niepoprawny status wartości {0} ", vValue.Status))
End If
v.Dispose()
End If

Return True

End Function

Public Sub FinalizeScript() Implements IScript.FinalizeScript

End Sub

End Class

Należy jednak pamiętać o tym, że intensywne wykorzystywanie forsowanego odczytu wartości zmiennej może mocno obciążyć łącze komunikacyjne i pogorszyć działanie całej aplikacji.


2.4.1 Cykliczny odczyt wartości bieżących zmiennych procesowych

Częstym przypadkiem jest konieczność cyklicznego odczytu i przetwarzania wartości zmiennej procesowej. W tego typu przypadkach można wykorzystać mechanizm okresowego wywołania wybranej funkcji.

Poniższy przykładowy skrypt zapisuje do pliku tekstowego wartości bieżące dwóch zmiennych. Zapis realizowany jest co 15 minut.

C#

using System;
using System.Windows.Forms;
using Askom.AsixEvo.Scripting;
using System.IO;

public class CurrValuesReport : IScript
{
   IApplication application;
   IVariable v1, v2;

   public bool Initialize(string[] aParameters, IApplication aApplication)
   {
      application = aApplication;
      v1 = aApplication.GetVariable(aParameters[0], true);
      v2 = aApplication.GetVariable(aParameters[1], true);
      aApplication.RegisterTimeEvent(Report15Min, TimeSpan.FromMinutes(15),

                                     TimeSpan.FromMinutes(0));
      return false;
   }

   public void FinalizeScript()
   {

   }

   void Report15Min()
   {
      StreamWriter writer = new StreamWriter(
         Path.Combine(application.ApplicationWorkingDirectory, "logs\\reports.txt"), true,
         System.Text.ASCIIEncoding.GetEncoding(1250));
      String msg = String.Format("{0},{1},{2}",
         DateTime.Now, v1.VariableState.IsGood ? v1.VariableState.Value : "?",
                       v2.VariableState.IsGood ? v2.VariableState.Value : "?");
      writer.WriteLine(msg);
      writer.Close();
   }
}

VB

Imports System
Imports System.Windows.Forms
Imports Askom.AsixEvo.Scripting
Imports System.IO

Public Class CurrentValuesReportVB
    Implements IScript

    Dim application As IApplication
    Dim v1, v2 As IVariable
    Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

                               IApplication) As Boolean Implements IScript.Initialize

        application = aApplication
        v1 = aApplication.GetVariable(aParameters(0), True)
        v2 = aApplication.GetVariable(aParameters(1), True)
        application.RegisterTimeEvent(Report15Min, TimeSpan.FromMinutes(15), _

                                      TimeSpan.FromMinutes(0))
        Return False

    End Function

    Public Sub FinalizeScript() Implements IScript.FinalizeScript

    End Sub

    Sub Report15Min()

        Dim writer As StreamWriter
        writer = New StreamWriter( _
           Path.Combine(application.ApplicationWorkingDirectory, "logs\\reports.txt"), True, _
           System.Text.ASCIIEncoding.GetEncoding(1250))
        Dim msg, v1v, v2v As String
        If v1.VariableState.IsGood Then v1v = v1.VariableState.Value Else v1v = "?"
        If v2.VariableState.IsGood Then v2v = v2.VariableState.Value Else v2v = "?"
        msg = String.Format("{0},{1},{2}", DateTime.Now, v1v, v2v)
        writer.WriteLine(msg)
        writer.Close()

    End Sub

End Class

W funkcji Initialize tworzone są dwa obiekty IVariable, które będą służyły do odczytu wartości zmiennych. Istotne jest ustawienie drugiego parametru funkcji GetVariable na True. Powoduje to włączenia odświeżania zmiennej procesowej – brak odświeżania mógłby spowodować, że w momencie pobrania wartości zmiennej w funkcji okresowej, wartość ta byłaby nieaktualna.

Funkcja RegisterTimeEvent rejestruje funkcję okresową Report15Min. Funkcja będzie wykonywana co 15 minut, w minucie 0, 15, 30 i 45.

Funkcja Initialize zwraca wartość False, co powoduje kontynuację pracy skryptu.

Wewnątrz funkcji Report15Min wykonywany jest zapis danych do pliku – wartości zmiennych są pobierane w standardowy sposób, za pośrednictwem właściwości VariableState.


2.4.2 Odczyt wartości bieżących sterowany odświeżaniem zmiennej

Inną metodą cyklicznego przetwarzania wartości zmiennych jest wykorzystanie funkcji RegisterStateEvent, która powoduje zarejestrowanie funkcji zwrotnej wywoływanej natychmiast po każdorazowym odświeżeniu wartości zmiennej. Pozwala to na natychmiastową reakcję na zmianę stanu zmiennej. Metoda funkcji zwrotnej wykorzystywana jest w takich scenariuszach jak automatyczne wyliczanie wartości pochodnych lub rozpoznawanie sytuacji alarmowych.

Przykład skryptu wykorzystującego funkcję RegisterStateEvent jest pokazany w rozdziale dotyczącym ustawiania wartości zmiennych (patrz: 2.5. Ustawianie wartości zmiennych procesowych).


2.5 Ustawianie wartości zmiennych procesowych

Podobnie jak w przypadku odczytu wartości zmiennych, ustawienie wartości można wykonać dwoma metodami. W prostych przypadkach, jednokrotnego zapisu wartości, należy stosować metodę SetVariableValue lub SetVariableBits interfejsu IApplication. Bardziej uniwersalnym sposobem działania jest wykorzystanie obiektów interfejsu IVariable. Wartość zmiennej można zmienić przy pomocy metod SetVariableValue i SetVariableBits tego interfejsu. Metoda SetVariableBits pozwala na zmianę pojedynczych bitów wartości zmiennej.


2.5.1 Wyliczanie wartości pochodnych zmiennych

Poniższy skrypt pokazuje, w jaki sposób na podstawie wartości dwóch zwykłych zmiennych wyliczana jest wartość trzeciej zmiennej. Skrypt pokazuje także zastosowanie funkcji zwrotnej odświeżania do monitorowania wartości zmiennych wejściowych.

C#

using System;
using System.Windows.Forms;
using Askom.AsixEvo.Scripting;

public class VarCalc : IScript
{
   IApplication application;
   IVariable vIn1, vIn2, vOut;

   public bool Initialize(string[] aParameters, IApplication aApplication)
   {
      application = aApplication;
      vIn1 = aApplication.GetVariable(aParameters[0], true);
      vIn2 = aApplication.GetVariable(aParameters[1], true);
      vOut = aApplication.GetVariable(aParameters[2], false);
      vIn1.RegisterStateEvent(RefreshedEvent);
      vIn2.RegisterStateEvent(RefreshedEvent);
      return false;
   }

   public void FinalizeScript()
   {

   }

   void RefreshedEvent(string aVariableName, VariableState aVariableState)
   {
      try
      {
         if (vIn1.VariableState.IsGood && vIn2.VariableState.IsGood)
         {
            vOut.SetVariableValue(Recalculate(Convert.ToDouble(vIn1.VariableState.Value),
               Convert.ToDouble(vIn2.VariableState.Value)));
         }
      }
      catch (Exception e)
      {
         application.ReportMessage(EvoMessageType.Error, e.Message);

      }
   }

   double Recalculate(double v1, double v2)
   {
      return v1 + v2;
   }

}

VB

Imports System
Imports System.Windows.Forms
Imports Askom.AsixEvo.Scripting

Public Class VarCalcVB
    Implements IScript

    Dim application As IApplication
    Dim vIn1, vIn2, vOut As IVariable

    Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

                               IApplication) As Boolean Implements IScript.Initialize

        application = aApplication
        vIn1 = aApplication.GetVariable(aParameters(0), True)
        vIn2 = aApplication.GetVariable(aParameters(1), True)
        vOut = aApplication.GetVariable(aParameters(2), False)
        vIn1.RegisterStateEvent(AddressOf RefreshedEvent)
        vIn2.RegisterStateEvent(AddressOf RefreshedEvent)
        Return False

    End Function

    Public Sub FinalizeScript() Implements IScript.FinalizeScript
    End Sub

    Sub RefreshedEvent(ByVal aVariableName As String, ByVal aVariableState As VariableState)

        Try
            If (vIn1.VariableState.IsGood And vIn2.VariableState.IsGood) Then

                vOut.SetVariableValue(

                       Recalculate(Convert.ToDouble(vIn1.VariableState.Value), _
                                   Convert.ToDouble(vIn2.VariableState.Value)))

            End If
        Catch e As Exception
            application.ReportMessage(EvoMessageType.Error, e.Message)
        End Try

    End Sub

    Function Recalculate(ByVal v1 As Double, ByVal v2 As Double) As Double

        Recalculate = v1 + v2

    End Function

End Class

W funkcji Initialize tworzone są dwa obiekty IVariable, które będą służyły do odczytu wartości zmiennych oraz jeden obiekt IVariable zmiennej wynikowej. Istotne jest ustawienie drugiego parametru funkcji GetVariable na True dla obu zmiennych wejściowych. Następnie dla zmiennych wejściowych, przy pomocy metody registerStateEvent, deklarowana jest funkcja zwrotna RefresehedEvent. Będzie ona wywoływana przy każdej zmianie wartości którejkolwiek ze zmiennych wejściowych.

Funkcja Initialize zwraca wartość false, co powoduje kontynuację pracy skryptu.

Wewnątrz funkcji RefreshedEvent następuje wyliczenie nowej wartości wynikowej, a następnie zmienna wynikowa jest ustawiana przy pomocy funkcji SetVariableValue. Parametry funkcji zwrotnej aVariableName i aVariableState mogą być użyte do określenia, która zmienna uległa zmianie i na jaką wartość, ale w przykładowym skrypcie nie było to potrzebne.

Należy zwrócić uwagę na sposób zabezpieczenia kodu przy pomocy konstrukcji try. Kod jest odporny na brak lub nieprawidłowe wartości zmiennych wejściowych.


2.5.2 Pozyskiwanie wartości ze źródeł zewnętrznych

Poniższy skrypt okresowo wykonuje operację ping do określonego urządzenia podanego adresem lub nazwą. Na podstawie wyniku ustawia wartość wskazanej zmiennej na true lub false. Zmienna wynikowa powinna znajdować się kanale typu None.

C#

using System;
using System.Windows.Forms;
using Askom.AsixEvo.Scripting;
using System.Net.NetworkInformation;

public class Ping : IScript
{
   IEventInfo mTimeTickInfo;
   System.Net.NetworkInformation.Ping mPing;
   IVariable mPingVar;
   string mHost;

   public bool Initialize(string[] aParameters, IApplication aApplication)
   {
      mHost = aParameters[0];

      mPing = new System.Net.NetworkInformation.Ping();
      mPingVar = aApplication.GetVariable(aParameters[1], false);

      if (mPingVar != null && mPing != null)
      {
         mTimeTickInfo = aApplication.RegisterTimeEvent(PingCheck, TimeSpan.FromSeconds(5),

                                                        TimeSpan.MinValue);
         return false;
      }
      else
         return true;
   }

   public void FinalizeScript()
   {
   }

   void PingCheck()
   {
      System.Net.NetworkInformation.PingReply reply = mPing.Send(mHost, 500);
      mPingVar.SetVariableValue(reply.Status==System.Net.NetworkInformation.IPStatus.Success);
   }
}

VB

Imports System
Imports System.Windows.Forms
Imports Askom.AsixEvo.Scripting

Public Class PingVB
    Implements IScript

    Dim mTimeTickInfo As IEventInfo
    Dim mPing As System.Net.NetworkInformation.Ping
    Dim mPingVar As IVariable
    Dim mHost As String

    Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

                                     IApplication) As Boolean Implements IScript.Initialize

        mHost = aParameters(0)

        mPing = New System.Net.NetworkInformation.Ping()
        mPingVar = aApplication.GetVariable(aParameters(1), False)

        If (mPingVar Is Nothing Or mPing Is Nothing) Then
            Return True
        Else
            mTimeTickInfo = aApplication.RegisterTimeEvent(AddressOf PingCheck, _

                                                 TimeSpan.FromSeconds(5), TimeSpan.MinValue)
            Return False
        End If

    End Function

    Public Sub FinalizeScript() Implements IScript.FinalizeScript
    End Sub

    Sub PingCheck()

        Dim reply As System.Net.NetworkInformation.PingReply

        reply = mPing.Send(mHost, 500)
        mPingVar.SetVariableValue(reply.Status=System.Net.NetworkInformation.IPStatus.Success)

    End Sub

End Class

Funkcja PingCheck wykonywana jest co 5 sekund. Na podstawie rezultatu funkcji Send obiektu klasy System.Net.NetworkInformation.Ping ustawiana jest wartość zmiennej procesowej.


2.6 Odczyt wartości archiwalnych zmiennych procesowych

Interfejs IVariable pozwala także na odczyt wartości archiwalnych zmiennych. Typowe zastosowanie to generacja raportów oraz wyliczanie wskaźników produkcyjnych bazujących na danych archiwalnych.

W poniższym przykładzie pokazano, w jaki sposób utworzyć prosty raport w formacie HTML.

C#

using System;
using System.IO;
using System.Windows.Forms;
using Askom.AsixEvo.Scripting;

public class RaportHtml : IScript
{
   public bool Initialize(string[] aParameters, IApplication aApplication)
   {
       IVariable v = aApplication.GetVariable(aParameters[0], false);
       if(v == null)
       {
          aApplication.ReportMessage( EvoMessageType.Error,

                          "Błąd generowania raportu: Brak zmiennej " + aParameters[0]);
          return true;
       }

       DateTime day = DateTime.Today;
       DateTime day0 = day.AddDays(-1);
       ArcQuery q = new ArcQuery(day0, day, "average", TimeSpan.FromHours(1));

       IArcQueryResult res = v.OrderArcData(q);

       int loopCnt = 0;
       while(res.ResultStatus == ArcResultStatus.Processing)
       {
          if(loopCnt > 200)
          {
             aApplication.ReportMessage(EvoMessageType.Error,                                                    "Błąd generowania raportu! Przekroczono czas oczekiwania na odpowiedź.");
             v.Dispose();
             return true;
          }

          aApplication.Sleep(TimeSpan.FromMilliseconds(100));
          loopCnt++;
       }

       if(res.ResultStatus == ArcResultStatus.Ready)
          {
             StreamWriter sw = null;
             System.Text.StringBuilder sb = new System.Text.StringBuilder();
             try
             {
                 sb.AppendLine(

   "<html><head><title>Raport - Srednie godzinowe z poprzedniego dnia</title></head><body>");               sb.AppendLine("<table width=\"25%\" align=\"center\" border=\"1\" >");
                sb.AppendLine("<tr><th>Godzina</th><th>Srednia</th></tr>");

                if(res.Values != null)
                {
                    foreach(ArcVariableState p in res.Values)
                    {

                         sb.AppendLine(

                 "<tr><td>" + p.TimeStamp.ToString() + "</td><td>" + p.Value + "</td></tr>");                  }
                }
                sb.AppendLine("</table>");
                sb.AppendLine("</body></html>");

                 string file = Path.Combine(aApplication.ApplicationWorkingDirectory,

                                             "reports\\report.html");

                sw = new StreamWriter(file);
                sw.Write(sb.ToString());
                System.Diagnostics.Process.Start(file);
             }
             catch(Exception ex)
             {
                aApplication.ReportMessage(EvoMessageType.Error,

                                                       "Błąd zapisu pliku: " + ex.Message);
             }
             finally
             {
                if(sw != null)
                {
                    sw.Close();
                    sw.Dispose();
                }
             }
          }
          else if(res.ResultStatus == ArcResultStatus.Error)
             aApplication.ReportMessage(EvoMessageType.Error,

"Błąd generowania raportu! " + res.ErrorDescription);

v.Dispose();
return true;
}

public void FinalizeScript()
{
}
}

VB

Imports System
Imports System.Windows.Forms
Imports Askom.AsixEvo.Scripting

Public Class RaportHtmlVB
    Implements IScript

    Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

                                      IApplication) As Boolean Implements IScript.Initialize

        Dim v As IVariable
        v = aApplication.GetVariable(aParameters(0), False)
        If (v Is Nothing) Then
            aApplication.ReportMessage(EvoMessageType.Error, _

                              "Błąd generowania raportu: Brak zmiennej " & aParameters(0))
            Return True
        End If

        Dim day, day0 As DateTime
        day = DateTime.Today
        day0 = day.AddDays(-1)
        Dim q As ArcQuery
        q = New ArcQuery(day0, day, "average", TimeSpan.FromHours(1))

        Dim res As IArcQueryResult
        res = v.OrderArcData(q)

        Dim loopCnt As Integer
        loopCnt = 0
        While (res.ResultStatus = ArcResultStatus.Processing)

            If (loopCnt > 200) Then
                aApplication.ReportMessage(EvoMessageType.Error, _
                 "Błąd generowania raportu! Przekroczono czas oczekiwania na odpowiedź.")
                v.Dispose()
                Return True
            End If

            aApplication.Sleep(TimeSpan.FromMilliseconds(100))
            loopCnt += 1

        End While

        If (res.ResultStatus = ArcResultStatus.Ready) Then

            Dim sw As System.IO.StreamWriter
            sw = Nothing
            Dim sb As System.Text.StringBuilder
            sb = New System.Text.StringBuilder()
            Try
                sb.AppendLine( _

     "<html><head><title>Raport - Srednie godzinowe z poprzedniego dnia</title></head><body>")
                sb.AppendLine("<table width=""25%"" align=""center"" border=""1"" >")
                sb.AppendLine("<tr><th>Godzina</th><th>Srednia</th></tr>")

                If (Not res.Values Is Nothing) Then

                    For Each p As ArcVariableState In res.Values
                        sb.AppendLine( _                   "<tr><td>" & p.TimeStamp.ToString() & "</td><td>" & p.Value & "</td></tr>")
                    Next p
                    sb.AppendLine("</table>")
                    sb.AppendLine("</body></html>")

                    Dim file As String
                    file = System.IO.Path.Combine( _

                             aApplication.ApplicationWorkingDirectory, "reports\\report.html")
                    sw = New System.IO.StreamWriter(file)
                    sw.Write(sb.ToString())
                    System.Diagnostics.Process.Start(file)

                End If

            Catch ex As Exception
                aApplication.ReportMessage(EvoMessageType.Error, _

                                                 "Błąd zapisu pliku: " & ex.Message)
            Finally
                If (Not sw Is Nothing) Then
                    sw.Close()
                    sw.Dispose()
                End If
            End Try
        ElseIf (res.ResultStatus = ArcResultStatus.Error) Then
            aApplication.ReportMessage(EvoMessageType.Error, _

"Błąd generowania raportu! " & res.ErrorDescription)
End If

v.Dispose()
Return True

End Function

Public Sub FinalizeScript() Implements IScript.FinalizeScript

End Sub

End Class

Odczyt wartości archiwalnych inicjowany jest wywołaniem funkcji OrderArcData interfejsu IVariable. Parametrem wywołania jest obiekt klasy ArcQuery określający, jakie dane i z jakiego okresu mają zostać pobrane. W przykładzie dane pobierane są z okresu poprzedniego dnia, a zwracane wartości to średnie 1-godzinowe.

Po zainicjowaniu odczytu należy zaczekać na koniec operacji poprzez testowanie statusu wykonania operacji ResultStatus (alternatywną metodą oczekiwania jest zadeklarowanie funkcji zwrotnej wywoływanej w momencie zakończenia odczytu). Po stwierdzeniu, że operacja zakończyła się poprawnie skrypt wykonuje generację raportu wynikowego. Wartości archiwalne zwracane są w kolekcji Values dostępnej poprzez obiekt statusu wykonania. Kolekcja składa się z obiektów ArcVariableState – każdy obiekt określa wartość, status i stempel czasu pojedynczej wartości archiwalnej.

Po wygenerowaniu raportu, wywołanie metody Start obiektu Process powoduje otwarcie raportu w oknie domyślnej przeglądarki www.


2.7 Użycie zmiennych tablicowych

Sposób użycia zmiennych tablicowych niewiele różni się od obsługi zwykłych zmiennych. Inny jest tylko sposób interpretacji właściwości Value obiektu VariableState.


2.7.1 Odczyt zmiennych tablicowych

Poniższy przykład zapisuje do logu komunikatów wartości wszystkich elementów zmiennej tablicowej o nazwie podanej w parametrach uruchomienia.

C#

using System;

using System.Windows.Forms;

using Askom.AsixEvo.Scripting;

public class TableGet : IScript

{

public bool Initialize(string[] aParameters, IApplication aApplication)

{

VariableState v = aApplication.GetVariableValue(aParameters[0], true);

int[] valTable = (int[])(v.Value);

System.Text.StringBuilder sb = new System.Text.StringBuilder();

foreach (int val in valTable)

{

sb.Append(val);

sb.Append(" ");

}

aApplication.ReportMessage(EvoMessageType.Info, sb.ToString());

return true;

}

public void FinalizeScript()

{

}

}

VB

Imports System

Imports System.Windows.Forms

Imports Askom.AsixEvo.Scripting

Public Class TableGetVB

Implements IScript

Public Function Initialize(ByVal aParameters() As String, ByVal aApplication _

As IApplication) As Boolean Implements IScript.Initialize

Dim v As VariableState = aApplication.GetVariableValue(aParameters(0), True)

Dim valTable() As Integer = v.Value

Dim sb As System.Text.StringBuilder = New System.Text.StringBuilder()

For Each val As Integer In valTable

sb.Append(val)

sb.Append(" ")

Next val

aApplication.ReportMessage(EvoMessageType.Info, sb.ToString())

Return True

End Function

Public Sub FinalizeScript() Implements IScript.FinalizeScript

End Sub

End Class

Kluczowym elementem skryptu jest podstawienie do zmiennej lokalnej ValTable właściwości Value obiektu stanu zmiennej procesowej połączone z odpowiednią deklaracją typu wartości. Istotne jest zachowanie zgodności typu zmiennej valTable z typem zmiennej procesowej wynikającym z jej definicji i sposobu pozyskania.

Oprócz pokazanego w przykładzie iterowania po wszystkich elementach tablicy, możliwy jest także bezpośredni odczyt dowolnego elementu poprzez użycie notacji indeksowej, np. valTable[5] (C#) lub valTable(5) (VB).


2.7.2 Zapis zmiennych tablicowych

Następny przykład pokazuje sposób wykorzystania zmiennych tablicowych do przechowywania wielu informacji w pojedynczej zmiennej. Skrypt odczytuje zawartość pliku tekstowego zawierającego komunikaty, które zostaną wyświetlone na diagramie. Odczytywanych jest pierwsze pięć linii pliku. Odczytane teksty zapisywane są do kolejnych elementów zmiennej procesowej.

Zakłada się, że wykorzystywana zmienna znajduje się w kanale typu NONE, a jej atrybut Typ wartości jest równy Table.

C#

using System;

using System.IO;

using System.Windows.Forms;

using Askom.AsixEvo.Scripting;

public class Messages : IScript

{

public bool Initialize(string[] aParameters, IApplication aApplication)

{

try

{

StreamReader file = new StreamReader(aParameters[0],System.Text.Encoding.Default);

string[] msgs = new string[5];

msgs[0] = file.ReadLine();

msgs[1] = file.ReadLine();

msgs[2] = file.ReadLine();

msgs[3] = file.ReadLine();

msgs[4] = file.ReadLine();

aApplication.SetVariableValue(aParameters[1], msgs);

file.Close();

}

catch (Exception e)

{

aApplication.ReportMessage(EvoMessageType.Info,"Error in Messages: " + e.Message);

}

return true;

}

public void FinalizeScript()

{

}

}

VB

Imports System

Imports System.IO

Imports System.Windows.Forms

Imports Askom.AsixEvo.Scripting

Public Class MessagesVB

Implements IScript

Public Function Initialize(ByVal aParameters() As String, ByVal aApplication _

As IApplication) As Boolean Implements IScript.Initialize

Try

Dim file As StreamReader = _

New StreamReader(aParameters(0), System.Text.Encoding.Default)

Dim msgs(4) As String

msgs(0) = file.ReadLine()

msgs(1) = file.ReadLine()

msgs(2) = file.ReadLine()

msgs(3) = file.ReadLine()

msgs(4) = file.ReadLine()

aApplication.SetVariableValue(aParameters(1),msgs)

file.Close()

Catch e As Exception

aApplication.ReportMessage(EvoMessageType.Info,"Error in Messages: " + e.Message)

End Try

Return True

End Function

Public Sub FinalizeScript() Implements IScript.FinalizeScript

End Sub

End Class

W skrypcie tworzona jest lokalna 5-elementowa zmienna tablicowa. Następnie na podstawie zawartości pliku tekstowego ustawiane są jej kolejne elementu. Działanie skryptu kończy standardowe wywołanie metody SetVariableValue interfejsu IApplication.

W obiektach diagramu można odwołać się do elementu zmiennej tablicowej przy pomocy funkcji TableElement, np. TableElement(Variable(zmienna),2).


2.8 Transfer przebiegów wzorcowych

Typowym zadaniem w przypadku aplikacji wykorzystujących przebiegi wzorcowe jest transfer definicji przebiegu do sterownika. Można to wykonać sekwencją operacji wysyłających kolejne punkty poprzez pojedynczą zmienną, ale z reguły lepszym wyjściem jest wysłanie całej definicji pojedynczą transmisją z wykorzystaniem zmiennej tablicowej.

Do odczytu przebiegów wzorcowych wykorzystywana jest metoda GetTrendPatternPoints interfejsu IApplication.

C#

using System;

using System.Windows.Forms;

using Askom.AsixEvo.Scripting;

public class Curve : IScript

{

    public bool Initialize(string[] aParameters, IApplication aApplication)

    {

        IVariable v = aApplication.GetVariable(aParameters[1], false);

        int varSize = Convert.ToInt32(v.VariableAttribute("ElementsCount"));

        int[] transferBuffer = new int[varSize];

        int pointsCount = 0;

        foreach (TrendPatternPoint point in

                                   aApplication.GetTrendPatternPoints(aParameters[0]))

        {

            if (pointsCount <= varSize - 2)

            {

                transferBuffer[pointsCount] = (int)point.TimeStamp.TotalSeconds;

                transferBuffer[pointsCount + 1] = (int)point.Value;

                pointsCount += 2;

            }

            else

            {

                if (pointsCount <= varSize)

                    transferBuffer[pointsCount] = 0;

                break;

            }

        }

        v.SetVariableValue(transferBuffer);

        v.Dispose();

        return true;

    }

    public void FinalizeScript()

    {

    }

}

VB

Imports System

Imports System.Windows.Forms

Imports Askom.AsixEvo.Scripting

Public Class CurveVB

    Implements IScript

    Public Function Initialize(ByVal aParameters() As String, ByVal aApplication _

                                   As IApplication) As Boolean Implements IScript.Initialize

        Dim v As IVariable = aApplication.GetVariable(aParameters(1), False)

        Dim varSize As Integer = Convert.ToInt32(v.VariableAttribute("ElementsCount"))

        Dim pointsCount As Integer = 0

        Dim transferBuffer() As Integer = New Integer(varSize) {}

        For Each point As TrendPatternPoint In _

                                        aApplication.GetTrendPatternPoints(aParameters(0))

            If pointsCount <= varSize - 2 Then

                transferBuffer(pointsCount) = CInt(point.TimeStamp.TotalSeconds)

                transferBuffer(pointsCount + 1) = CInt(point.Value)

                pointsCount += 2

            Else

                If (pointsCount <= varSize) Then transferBuffer(pointsCount) = 0

                Exit For

            End If

        Next point

        v.SetVariableValue(transferBuffer)

        v.Dispose()

        Return True

    End Function

    Public Sub FinalizeScript() Implements IScript.FinalizeScript

    End Sub

End Class

Pierwszą operacją w skrypcie jest odczyt atrybutu ElementsCount zmiennej docelowej w celu określenia wielkości dostępnego bufora. Zakłada się, że typem elementów zmiennej jest 32-bitowa liczba całkowita. Dodatkowo tworzona jest tablica transferBuffer, o rozmiarze zgodnym z wielkością zmiennej procesowej.

Następnie kolejne punkty przebiegu wzorcowego (pobrane metodą GetTrendPatternPoints) są zapisywane do kolejnych elementów tablicy transferBuffer, parami przesunięcie czasowe i wartość punktu. Jeżeli przebieg nie wypełnia całej tablicy, to dodawana jest pojedyncza wartość zerowa oznaczająca koniec przebiegu.

Działanie skryptu kończy standardowe wywołanie metody SetVariableValue.


2.9 Kontrola stanu alarmów

Usługi modelu obiektowego skryptu pozwalają na pełną kontrolę pracy systemu alarmów aplikacji. Dotyczy to zarówno monitorowania stanu alarmów, jak i programowego wykrywania zdarzeń alarmowych.


2.9.1 Odczyt stanu alarmów aktywnych

Dostęp do aktualnego stanu systemu alarmów zapewnia grupa metod interfejsu IApplication. Podstawowe funkcje to: GetActiveAlarms zwracająca kolekcję identyfikatorów alarmów znajdujących się aktualnie w logu alarmów aktywnych, GetDefinedAlarms pozwalająca na dostęp do wszystkich zdefiniowanych alarmów, oraz GetAlarm zwracająca referencją do interfejsu IAlarm. Właściwości i metody tego interfejsu pozwalają na odczyt wszystkich danych dotyczących konkretnego alarmu – jego definicji i aktualnego stanu.

Przedstawiony przykład pokazuje sposób stworzenia prostego raportu, w którym zapisywane są podstawowe informacje o wszystkich alarmach aktywnych w momencie wykonania skryptu.

Skrypt wymaga podania dwóch parametrów: nazwy domeny i nazwy pliku wynikowego.

C#

using System;

using System.IO;

using System.Windows.Forms;

using Askom.AsixEvo.Scripting;

public class AlarmReport : IScript

{

    public bool Initialize(string[] aParameters, IApplication aApplication)

    {

        try

        {

            StreamWriter sw = new StreamWriter

                                      (aParameters[1], false, System.Text.Encoding.UTF8);

            foreach (string aid in aApplication.GetActiveAlarms(aParameters[0]))

            {

                IAlarm alarm = aApplication.GetAlarm(aid);

                if (alarm.AlarmState.IsActive && !alarm.AlarmState.IsFinished)

                {

                    String desc = String.Format

                        ("{0:dd-MM-yyyy hh:mm:ss.fff} {1,10} {2,-40} {3}",

                        alarm.AlarmState.BeginTimeStamp, alarm.Id,

                        alarm.AlarmState.FormattedBeginText, alarm.AlarmState.BeginExprValue);

                    sw.WriteLine(desc);

                }

            }

            sw.Close();

        }

        catch (Exception)

        {

        }

        return true;

    }

    public void FinalizeScript()

    {

    }

}

VB

Imports System

Imports System.IO

Imports System.Windows.Forms

Imports Askom.AsixEvo.Scripting

Public Class AlarmReportVB

    Implements IScript

    Public Function Initialize(ByVal aParameters() As String, ByVal aApplication _

                                    As IApplication) As Boolean Implements IScript.Initialize

        Try

            Dim sw As StreamWriter = New StreamWriter _

                                         (aParameters(1), False, System.Text.Encoding.UTF8)

            For Each aid As String In aApplication.GetActiveAlarms(aParameters(0))

                Dim alarm As IAlarm = aApplication.GetAlarm(aid)

                If alarm.AlarmState.IsActive And Not alarm.AlarmState.IsFinished Then

                    Dim desc As String = String.Format _

                        ("{0:dd-MM-yyyy hh:mm:ss.fff} {1,10} {2,-40} {3}", _

                        alarm.AlarmState.BeginTimeStamp, alarm.Id, _

                        alarm.AlarmState.FormattedBeginText, alarm.AlarmState.BeginExprValue)

                    sw.WriteLine(desc)

                End If

            Next aid

            sw.Close()

        Catch a As Exception

        End Try

        Return True

    End Function

    Public Sub FinalizeScript() Implements IScript.FinalizeScript

    End Sub

End Class

Funkcja GetActiveAlarms zwraca kolekcję identyfikatorów wszystkich alarmów z wybranej domeny, które znajdują się w danym momencie w logu alarmów aktywnych. Następnie dla każdego z tych alarmów, funkcją GetAlarm pobierana jest referencja do obiektu IAlarm. Poprzez tę referencję pobierane są wszystkie dane o alarmie. W instrukcji if sprawdzane jest, czy alarm jest aktywny. Test AlarmState.IsActive sprawdza, czy alarm jest w logu alarmów aktywnych. Druga część testu używa właściwości AlarmState.IsFinished w celu określenia, czy alarm nie jest już zakończony – w logu alarmów aktywnych mogą być przez pewien czas przechowywane dane o alarmie niedawno zakończonym. Po stwierdzeniu, że alarm jest na pewno aktywny, wybrane informacje o alarmie są zapisywane do pliku.


2.9.2 Aktywne monitorowanie stanu alarmów

Oprócz pokazanego w poprzednim przykładzie okresowego odczytywania stanu alarmów, możliwe jest również monitorowanie aktywne. W tym wariancie można natychmiast zareagować na pojawienie się alarmu lub inną zmianę jego stanu. Funkcję monitorującą stan konkretnego alarmu można zadeklarować przy pomocy metody RegisterStateEvent interfejsu IAlarm. Przykładowy kod znajduje się w opisie metody RegisterStateEvent. (Patrz: 3.3.2.3 RegisterStateEvent ). Możliwe jest też monitorowanie stanu całej domeny alarmów. W tym celu należy użyć metodę RegisterAlarmDomainEvents interfejsu IApplication.


2.9.3 Zgłaszanie alarmów

Skrypty mogą realizować pełną funkcjonalność strategii wykrywania alarmów. Przykład z tego rozdziału realizuje taką strategię. Jej działanie oparte jest na cyklicznym odczycie pliku tekstowego, w którym zapisywane są (przez zewnętrzny program kontrolujący stan systemu) tekstowe identyfikatory alarmów rozdzielone znakami średnika. Obecność identyfikatora w pliku oznacza, że alarm jest aktywny. Zadaniem skryptu jest przekazanie informacji z pliku do systemu alarmów aplikacji. Wstępnym krokiem, który należy wykonać jest zdefiniowanie strategii alarmowej typu „Zewnętrzna” oraz definicji alarmów należących do tej strategii. W definicji każdego z alarmów, w atrybucie „Parametry wykrywania”, należy podać identyfikator, który w pliku tekstowym będzie odpowiadał temu alarmowi.

Przykładowy skrypt w momencie uruchomienia wymaga podania trzech parametrów: nazwy pliku tekstowego, nazwy domeny alarmowej oraz nazwy strategii, na konto której skrypt będzie działał. Uruchomienie skryptu należy zlecić w terminarzu aplikacji przy pomocy akcji Script. Akcję należy uruchamiać w trybie „Jednokrotnie przy starcie aplikacji”.

C#

using System;

using System.IO;

using System.Windows.Forms;

using Askom.AsixEvo.Scripting;

using System.Collections.Generic;

public class AlarmStrat : IScript

{

    IApplication application;

    string alarmStateFile;

    string domain;

    string strategy;

    List<IAlarm> myAlarms = new List<IAlarm>();

    public bool Initialize(string[] aParameters, IApplication aApplication)

    {

        application = aApplication;

        alarmStateFile = aParameters[0];

        domain = aParameters[1];

        strategy = aParameters[2];

        foreach (string name in application.GetDefinedAlarms(domain))

        {

            IAlarm ia = application.GetAlarm(domain, name);

            if (ia.Definition.Strategy == strategy)

                myAlarms.Add(ia);

        }

        aApplication.RegisterTimeEvent(StrategyFun, TimeSpan.FromSeconds(10),

                                       TimeSpan.FromSeconds(0));

        return false;

    }

    public void FinalizeScript()

    {

    }

    char[] separator = { ';' };

    void StrategyFun()

    {

        if (application.GetAlarmDomainStationMode(domain)!=AlarmStationMode.ActiveController)

            return;

        try

        {

            StreamReader file = new StreamReader(alarmStateFile,System.Text.Encoding.Default);

            List<string> content = new List<string>(file.ReadToEnd().Split(separator));

            foreach (IAlarm alarm in myAlarms)

            {

                bool isOn = content.IndexOf(alarm.Definition.DetectionParameters) != -1;

                if (isOn)

                {

                    if (!alarm.AlarmState.IsActive || alarm.AlarmState.IsFinished)

                    {

                        alarm.Raise();

                    }

                }

                else

                {

                    if (alarm.AlarmState.IsActive && !alarm.AlarmState.IsFinished)

                    {

                        alarm.Cancel();

                    }

                }

            }

            file.Close();

        }

        catch (Exception e)

        {

            application.ReportMessage(EvoMessageType.Info, "Error in AlarmStrat: "+e.Message);

        }

    }

}

VB

Imports System

Imports System.IO

Imports System.Windows.Forms

Imports System.Collections.Generic

Imports Askom.AsixEvo.Scripting

Public Class AlarmStratVb

    Implements IScript

    Dim application As IApplication

    Dim alarmStateFile As String

    Dim domain As String

    Dim strategy As String

    Dim myAlarms As List(Of IAlarm) = New List(Of IAlarm)

    Public Function Initialize(ByVal aParameters() As String, ByVal aApplication _

                               As IApplication) As Boolean Implements IScript.Initialize

        application = aApplication

        alarmStateFile = aParameters(0)

        domain = aParameters(1)

        strategy = aParameters(2)

        Dim ia As IAlarm

        For Each name As String In application.GetDefinedAlarms(domain)

            ia = application.GetAlarm(domain, name)

            If (ia.Definition.Strategy = strategy) Then

                myAlarms.Add(ia)

            End If

        Next name

        aApplication.RegisterTimeEvent(AddressOf StrategyFun, TimeSpan.FromSeconds(10),_

                                       TimeSpan.FromSeconds(0))

        Return False

    End Function

    Public Sub FinalizeScript() Implements IScript.FinalizeScript

    End Sub

    Dim separator() As Char = {";"}

    Public Sub StrategyFun()

        If application.GetAlarmDomainStationMode(domain) <> _

                                                     AlarmStationMode.ActiveController Then

            Return

        End If

        Try

            Dim file As StreamReader = New StreamReader(alarmStateFile, _

                                                        System.Text.Encoding.Default)

            Dim content As List(Of String) = New List(Of String) _

                                                        (file.ReadToEnd().Split(separator))

            For Each alarm As IAlarm In myAlarms

                Dim isOn As Boolean = _

                              Not content.IndexOf(alarm.Definition.DetectionParameters) = -1

                If isOn Then

                    If (Not alarm.AlarmState.IsActive) Or alarm.AlarmState.IsFinished Then

                        alarm.Raise()

                    End If

                Else

                    If alarm.AlarmState.IsActive And (Not alarm.AlarmState.IsFinished) Then

                        alarm.Cancel()

                    End If

                End If

            Next alarm

            file.Close()

        Catch e As Exception

            application.ReportMessage(EvoMessageType.Info, "Error in AlarmStrat: "+e.Message)

        End Try

    End Sub

End Class

W funkcji Initialize tworzona jest lista wszystkich alarmów należących do wskazanej parametrami domeny i strategii alarmowej. Funkcja GetDefinedAlarms zwraca wszystkie alarmy domeny. Następnie dla każdego alarmu domeny pobierana jest referencja do interfejsu IAlarm, a poprzez nią sprawdzane jest, czy alarm należy do właściwej strategii. Po odczycie danych konfiguracyjnych rejestrowana jest funkcja StrategyFun – będzie ona wykonywana co 10 sekund.

Funkcja StrategyFun sprawdza na początku tryb pracy domeny. Alarmy są wykrywane tylko wtedy, gdy stanowisko jest kontrolerem aktywnym domeny. Następnie odczytywany jest plik tekstowy i parsowana lista identyfikatorów. Dla każdego alarmu strategii określany jest aktualny stan alarmu wg danych odczytanych z pliku oraz status w aplikacji. W przypadku wykrycia niezgodności alarm jest zgłaszany przy pomocy metody Raise lub wygaszany metodą Cancel. Obie metody pozwalają potencjalnie na zgłoszenie dodatkowych danych związanych ze zdarzeniem. Dane te byłyby zapisane w logu alarmów. Możliwe jest też jawne podanie czasu zdarzenia – w przykładowym skrypcie czas zdarzenia jest identyczny z czasem wykonania funkcji Raise lub Cancel.

Wykrywanie aktualnego stanu alarmu wykonywane jest zgodnie z opisem podanym w przykładzie dotyczącym odczytu stanu alarmów.


2.10 Użycie kontekstu uruchomienia skryptu

Jedną z metod uruchomienia skryptu jest użycie akcji Script podpiętej do obsługi zdarzenia obiektu wizualizacyjnego na diagramie. W takim przypadku możliwe jest sprawdzenie kontekstu uruchomienia – pozwala to napisać skrypt, który dostosowuje się do miejsca wywołania.

Kontekst uruchomienie opisuje obiekt interfejsu IContext, który można uzyskać poprzez odczyt właściwości ExecutionContext interfejsu IApplication. Najbardziej użyteczną właściwością obiektu IContext jest MainVar zwracająca nazwę zmiennej głównej obiektu, dla którego skrypt został uruchomiony.

C#

using System;

using System.Windows.Forms;

using Askom.AsixEvo.Scripting;

public class Context : IScript

{

   public bool Initialize(string[] aParameters, IApplication aApplication)

   {

      string mainVar = aApplication.ExecutionContext.MainVariable;

      if (!string.IsNullOrEmpty(mainVar))

      {

         IVariable v = aApplication.GetVariable(mainVar, false);

         if (v != null)

         {

            try

            {

               if (v.VariableState.IsGood)

               {

                  v.SetVariableValue((UInt32)v.VariableState.Value + 1);

               }

            }

            catch (Exception e)

            {

               aApplication.ReportMessage(EvoMessageType.Error, e.Message);

            }

            finally

            {

               v.Dispose();

            }

         }

      }

      return true;

   }

   public void FinalizeScript()

   {

   }

}

VB

Imports System

Imports System.Windows.Forms

Imports Askom.AsixEvo.Scripting

Public Class ContextVB

    Implements IScript

    Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

                                     IApplication) As Boolean Implements IScript.Initialize

        Dim mainVar As String

        mainVar = aApplication.ExecutionContext.MainVariable

        If Not String.IsNullOrEmpty(mainVar) Then

            Dim v As IVariable

            v = aApplication.GetVariable(mainVar, False)

            If Not v Is Nothing Then

                Try

                    If (v.VariableState.IsGood) Then

                        v.SetVariableValue(v.VariableState.Value + 1)

                    End If

                Catch e As Exception

                    aApplication.ReportMessage(EvoMessageType.Error, e.Message)

                Finally

                    v.Dispose()

                End Try

            End If

        End If

        Return True

    End Function

    Public Sub FinalizeScript() Implements IScript.FinalizeScript

    End Sub

End Class

W powyższym przykładzie z kontekstu uruchomienia pobierana jest nazwa zmiennej głównej. Następnie, w przypadku poprawnego odczytu wartości aktualnej, wartość zmiennej jest inkrementowana.

Alternatywną metodą kontekstowego uruchomienia skryptu w obsłudze zdarzenia obiektu, jest dynamiczna konstrukcja treści akcji operatorskiej i przekazanie danych kontekstowych w parametrach skryptu.

Przykład:

^Script(Context,LocalProperty(ControlVar))

Powyższa akcja uruchamia skrypt Context z przekazaniem jako parametru nazwy zmiennej sterowanej obiektu, w kontekście którego akcja jest wykonywana.


2.11 Skrypty wielojęzyczne

W przypadku skryptów pracujących w ramach aplikacji wielojęzycznej istotne staje się użycie tekstów zgodnych z aktualnym językiem pracy aplikacji. W tego typu skryptach możliwe jest użycie dwóch mechanizmów. Można wykorzystać pulę wielojęzycznych napisów aplikacji lub wyliczać właściwą postać napisu w kodzie skryptu.

C#

using System;
using System.Windows.Forms;
using Askom.AsixEvo.Scripting;

public class LangMessage : IScript
{
   IApplication application;
   public bool Initialize(string[] aParameters, IApplication aApplication)
   {
      application = aApplication;
      aApplication.ReportMessage(EvoMessageType.Info,

                                 aApplication.ApplicationText("ScriptStartInfo"));
      aApplication.ReportMessage(EvoMessageType.Info, StartMsg());
      return true;
   }

   public void FinalizeScript()
   {
   }

   string StartMsg()
   {
      switch (application.CurrentApplicationLanguage)
      {
         case "pl":
            return "Skrypt uruchomiony";

         case "en":
         default:
            return "Script started";
      }
   }
}

VB

Imports System
Imports System.Windows.Forms
Imports Askom.AsixEvo.Scripting

Public Class LangMessageVB
    Implements IScript

    Dim application As IApplication
    Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

                                      IApplication) As Boolean Implements IScript.Initialize

        application = aApplication
        aApplication.ReportMessage(EvoMessageType.Info, _

                                   aApplication.ApplicationText("ScriptStartInfo"))
        aApplication.ReportMessage(EvoMessageType.Info, StartMsg())
        Return True

    End Function

    Public Sub FinalizeScript() Implements IScript.FinalizeScript
    End Sub

    Function StartMsg() As String

        Select Case application.CurrentApplicationLanguage

            Case "pl"
                Return "Skrypt uruchomiony"

            Case "en"
                Return "Script started"
            Case Else
                Return "Script started"

        End Select

    End Function

End Class

W powyższym kodzie w pierwszym wywołaniu metody ReportMessage treść komunikatu pobierana jest z puli napisów aplikacji przy pomocy metody ApplicationText. Parametr „ScriptStartInfo” jest identyfikatorem napisu użytym w puli napisów aplikacji. Metoda ApplicationText zwraca wersję napisu zgodną z aktualnym językiem pracy.

W drugim wywołaniu ReportMessage treść komunikatu jest określona przez funkcję StartMsg. Funkcja ta wylicza właściwą wersję językową na podstawie aktualnej wartości właściwości CurrentApplicationLanguage interfejsu IApplication.


2.12 Tworzenie interfejsu okienkowego

Skrypty systemu Asix.Evo pozwalają także na budowę własnych okienek interakcji z użytkownikiem aplikacji. Asix.Evo nie udostępnia żadnych specjalnych mechanizmów tworzenia okien – projektant aplikacji może za to wykorzystywać wszystkie środki udostępniane przez platformę programową .NET.


2.12.1 Wyświetlanie komunikatów

Najprostszym typem okienka są okienka komunikatów, rozszerzone ewentualnie o możliwość zapytania użytkownika o proste decyzje typu Tak/Nie. Najłatwiej taką funkcjonalność zrealizować używają metodę Show klasy System.Windows.Forms.MessageBox.

C#

using System;
using System.Windows.Forms;
using Askom.AsixEvo.Scripting;

public class Message : IScript
{
   public bool Initialize(string[] aParameters, IApplication aApplication)
   {
      if (aApplication.HasRole("SuperUser"))
      {
         DialogResult result = MessageBox.Show("Czy włączyć pracę linii ?", "Start",

                                                                   MessageBoxButtons.YesNo);
         if (result == DialogResult.Yes)
         {
            IVariable v = aApplication.GetVariable("LineState", false);
            v.SetVariableBits(1, 1);
            v.Dispose();
         }
      }
      else
         MessageBox.Show("Nie masz wystarczających uprawnień !", "Brak zezwolenia");
      return true;
   }

   public void FinalizeScript()
   {

   }
}

VB

Imports System
Imports System.Windows.Forms
Imports Askom.AsixEvo.Scripting

Public Class MessageVB
    Implements IScript

    Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

                                      IApplication) As Boolean Implements IScript.Initialize

        If aApplication.HasRole("SuperUser") Then

            Dim result As DialogResult
            result = MessageBox.Show("Czy włączyć pracę linii ?", "Start", _

                                                            MessageBoxButtons.YesNo)
            If result = DialogResult.Yes Then

                Dim v As IVariable
                v = aApplication.GetVariable("LineState", False)
                v.SetVariableBits(1, 1)
                v.Dispose()

            End If

        Else
            MessageBox.Show("Nie masz wystarczających uprawnień !", "Brak zezwolenia")
        End If

        Return True

    End Function

    Public Sub FinalizeScript() Implements IScript.FinalizeScript

    End Sub

End Class

Skrypt sprawdza, czy zalogowany użytkownik należy do roli SuperUser. Jeżeli tak, to wyświetlane jest okno komunikatu z zapytaniem, czy uruchomić pracę linii. Po pozytywnej odpowiedzi użytkownika najmłodszy bit zmiennej LineState ustawiany jest na wartość 1.


2.12.2 Okna budowane w treści skryptu

W treści skryptu można także skonstruować programowo okno dialogowe. Można zbudować okno dowolnie skomplikowane, jednakże ta technika sprawdza się dla okien niezbyt dużych.

W poniższym przykładzie tworzone jest okno złożone z dwóch tekstowych pól edycyjnych oraz dwóch przycisków.

C#

using System;
using System.Windows.Forms;
using Askom.AsixEvo.Scripting;

public class FormBuilder : IScript
{
   Form entryForm;
   TextBox xPos, yPos;

   public bool Initialize(string[] aParameters, IApplication aApplication)
   {

      IVariable varX, varY;

      varX = aApplication.GetVariable(aParameters[0], true);
      varY = aApplication.GetVariable(aParameters[1], true);

      CreateForm();

      xPos.Text = varX.VariableState.FormattedValue;
      yPos.Text = varY.VariableState.FormattedValue;
      DialogResult res = entryForm.ShowDialog();
      if (res == DialogResult.OK)
      {
         Int32 newX, newY;
         if (Int32.TryParse(xPos.Text, out newX) && Int32.TryParse(yPos.Text, out newY))
         {
            varX.SetVariableValue(newX);
            varY.SetVariableValue(newY);
         }
         else
            MessageBox.Show("Niepoprawne wartości");
      }

      varX.Dispose();
      varX.Dispose();
      return true;
   }

   public void FinalizeScript()
   {
   }

   void CreateForm()
   {
      Label label1 = new Label();
      label1.AutoSize = true;
      label1.Location = new System.Drawing.Point(24, 29);
      label1.Size = new System.Drawing.Size(54, 13);
      label1.Text = "Pozycja X";

      xPos = new TextBox();
      xPos.Location = new System.Drawing.Point(97, 26);
      xPos.Size = new System.Drawing.Size(132, 20);

      Label label2 = new Label();
      label2.AutoSize = true;
      label2.Location = new System.Drawing.Point(24, 68);
      label2.Size = new System.Drawing.Size(54, 13);
      label2.Text = "Pozycja Y";

      yPos = new System.Windows.Forms.TextBox();
      yPos.Location = new System.Drawing.Point(97, 65);
      yPos.Size = new System.Drawing.Size(132, 20);

      Button buttonOk = new Button();
      buttonOk.DialogResult = DialogResult.OK;
      buttonOk.Location = new System.Drawing.Point(280, 20);
      buttonOk.Size = new System.Drawing.Size(142, 30);
      buttonOk.Text = "&OK";
      buttonOk.UseVisualStyleBackColor = true;

      Button buttonCancel = new Button();
      buttonCancel.DialogResult = DialogResult.Cancel;
      buttonCancel.Location = new System.Drawing.Point(280, 59);
      buttonCancel.Size = new System.Drawing.Size(142, 30);
      buttonCancel.Text = "&Anuluj";
      buttonCancel.UseVisualStyleBackColor = true;

      entryForm = new Form();
      entryForm.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
      entryForm.AutoScaleMode = AutoScaleMode.Font;
      entryForm.CancelButton = buttonCancel;
      entryForm.ClientSize = new System.Drawing.Size(466, 103);
      entryForm.Controls.Add(buttonCancel);
      entryForm.Controls.Add(buttonOk);
      entryForm.Controls.Add(yPos);
      entryForm.Controls.Add(label2);
      entryForm.Controls.Add(xPos);
      entryForm.Controls.Add(label1);
      entryForm.FormBorderStyle = FormBorderStyle.FixedSingle;
      entryForm.MaximizeBox = false;
      entryForm.MinimizeBox = false;
      entryForm.StartPosition = FormStartPosition.CenterScreen;
      entryForm.Text = "Koordynaty";
      entryForm.TopMost = true;
   }
}

VB

Imports System
Imports System.Windows.Forms
Imports Askom.AsixEvo.Scripting

Public Class FormBuilderVB
    Implements IScript

    Dim entryForm As Form
    Dim xPos, yPos As TextBox

    Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

                                     IApplication) As Boolean Implements IScript.Initialize

        Dim varX, varY As IVariable

        varX = aApplication.GetVariable(aParameters(0), True)
        varY = aApplication.GetVariable(aParameters(1), True)

        CreateForm()

        xPos.Text = varX.VariableState.FormattedValue
        yPos.Text = varY.VariableState.FormattedValue
        If (entryForm.ShowDialog() = DialogResult.OK) Then

            Dim newX, newY As Int32
            If (Int32.TryParse(xPos.Text, newX) And Int32.TryParse(yPos.Text, newY)) Then
                varX.SetVariableValue(newX)
                varY.SetVariableValue(newY)
            Else
                MessageBox.Show("Niepoprawne wartości")
            End If

        End If

        varX.Dispose()
        varX.Dispose()

        Return True

    End Function

    Public Sub FinalizeScript() Implements IScript.FinalizeScript

    End Sub

    Sub CreateForm()

        Dim label1 As Label
        label1 = New Label()
        label1.AutoSize = True
        label1.Location = New System.Drawing.Point(24, 29)
        label1.Size = New System.Drawing.Size(54, 13)
        label1.Text = "Pozycja X"

        xPos = New TextBox()
        xPos.Location = New System.Drawing.Point(97, 26)
        xPos.Size = New System.Drawing.Size(132, 20)

        Dim label2 As Label
        label2 = New Label()
        label2.AutoSize = True
        label2.Location = New System.Drawing.Point(24, 68)
        label2.Size = New System.Drawing.Size(54, 13)
        label2.Text = "Pozycja Y"

        yPos = New System.Windows.Forms.TextBox()
        yPos.Location = New System.Drawing.Point(97, 65)
        yPos.Size = New System.Drawing.Size(132, 20)

        Dim buttonOk As Button
        buttonOk = New Button()
        buttonOk.DialogResult = DialogResult.OK
        buttonOk.Location = New System.Drawing.Point(280, 20)
        buttonOk.Size = New System.Drawing.Size(142, 30)
        buttonOk.Text = "&OK"
        buttonOk.UseVisualStyleBackColor = True

        Dim buttonCancel As Button
        buttonCancel = New Button()
        buttonCancel.DialogResult = DialogResult.Cancel
        buttonCancel.Location = New System.Drawing.Point(280, 59)
        buttonCancel.Size = New System.Drawing.Size(142, 30)
        buttonCancel.Text = "&Anuluj"
        buttonCancel.UseVisualStyleBackColor = True

        entryForm = New Form()
        entryForm.AutoScaleDimensions = New System.Drawing.SizeF(6.0F, 13.0F)
        entryForm.AutoScaleMode = AutoScaleMode.Font
        entryForm.CancelButton = buttonCancel
        entryForm.ClientSize = New System.Drawing.Size(466, 103)
        entryForm.Controls.Add(buttonCancel)
        entryForm.Controls.Add(buttonOk)
        entryForm.Controls.Add(yPos)
        entryForm.Controls.Add(label2)
        entryForm.Controls.Add(xPos)
        entryForm.Controls.Add(label1)
        entryForm.FormBorderStyle = FormBorderStyle.FixedSingle
        entryForm.MaximizeBox = False
        entryForm.MinimizeBox = False
        entryForm.StartPosition = FormStartPosition.CenterScreen
        entryForm.Text = "Koordynaty"
        entryForm.TopMost = True

    End Sub

End Class

Funkcja CreateForm tworzy programowo obiekt okienka dialogowego. Przed otwarciem okienka, pola edycyjne ustawiane są zgodnie z aktualnymi wartościami zmiennych przekazanych w parametrach wywołania skryptu. Następnie okienko jest otwierane w trybie dialogowym przy pomocy metody ShowDialog obiektu okienka. Powrót do kodu skryptu następuje po zamknięciu okienka. Jeżeli zostało zamknięte klawiszem OK, to wykonywana jest próba konwersji wprowadzonych wartości na liczby typu całkowitego i wysłanie nowych wartości do zmiennych procesowych.


2.12.3 Użycie dołączanych bibliotek

Alternatywną do bezpośredniego programowego tworzenia okna dialogowego jest budowanie okien w zewnętrznym środowisku typu VisualStudio, kompilowaniu ich do postaci plików dll, a następnie użyciu w skrypcie Asix.Evo jedynie odwołania do gotowego kodu.

W poniższym przykładzie użyta zostanie biblioteka o nazwie EvoDialog.dll, w której znajduje się kod klasy EvoDialog dziedziczącej po System.Windows.Forms.Form. Klasa EvoDialog udostępnia dwie właściwości służące do ustawienia wartości wejściowych oraz jedną właściwość, w której po zamknięciu okna zostanie zapisana nazwa diagramu.

C#

using System;

using System.Windows.Forms;

using Askom.AsixEvo.Scripting;

using EvoAddOns;

public class Dialog : IScript

{

   public bool Initialize(string[] aParameters, IApplication aApplication)

   {

      IVariable varX, varY;

      varX = aApplication.GetVariable(aParameters[0], true);

      varY = aApplication.GetVariable(aParameters[1], true);

      EvoDialog dialog = new EvoDialog();

      dialog.XPos = varX.VariableState.FormattedValue;

      dialog.YPos = varY.VariableState.FormattedValue;

      if (dialog.ShowDialog() == DialogResult.OK)

      {

         if (!String.IsNullOrEmpty(dialog.Diagram))

            aApplication.ExecuteAction(EvoMessageType.Info,

                                      "OpenWindow(Main,P1," + dialog.Diagram + ",null)");

      }

      varX.Dispose();

      varY.Dispose();

      return true;

   }

   public void FinalizeScript()

   {

   }

}

VB

Imports System

Imports System.Windows.Forms

Imports Askom.AsixEvo.Scripting

Imports EvoAddOns

Public Class DialogVB

    Implements IScript

    Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

                                      IApplication) As Boolean Implements IScript.Initialize

        Dim varX, varY As IVariable

        varX = aApplication.GetVariable(aParameters(0), True)

        varY = aApplication.GetVariable(aParameters(1), True)

        Dim dialog As EvoDialog

        dialog = New EvoDialog()

        dialog.XPos = varX.VariableState.FormattedValue

        dialog.YPos = varY.VariableState.FormattedValue

        If dialog.ShowDialog() = DialogResult.OK Then

            If Not String.IsNullOrEmpty(dialog.Diagram) Then

                aApplication.ExecuteAction(EvoMessageType.Info, _

                                           "OpenWindow(Main,P1," & dialog.Diagram & ",null)")

            End If

        End If

        varX.Dispose()

        varY.Dispose()

        Return True

    End Function

    Public Sub FinalizeScript() Implements IScript.FinalizeScript

    End Sub

End Class

W powyższym kodzie tworzony jest obiekt okienka EvoDialog. Następnie właściwości okienka XPos i YPos ustawiane są zgodnie z aktualnymi wartościami dwóch zmiennych o nazwach przekazanych w parametrach startowych skryptu. Okno dialogowe jest otwierane przy pomocy funkcji ShowDialog, a w przypadku zamknięcia okna ze statusem DialogResult.OK, konstruowana i wykonywana jest akcja operatorska otwierająca diagram o nazwie przekazanej we właściwości Diagram okienka.

Ażeby przykładowy skrypt wykonał się poprawnie, muszą być spełnione dwa dodatkowe warunki:

  • plik EvoDialog.dll (wraz z ewentualnymi dodatkowymi bibliotekami) musi być skopiowany do podkatalogu Addons katalogu definicyjnego aplikacji.

  • w zakładce Referencje panelu edycyjnego skryptu należy dodać referencję do pliku EvoDialog.dll.

Opisana technika rozszerzania funkcjonalności skryptu poprzez dołączanie bibliotek, może być stosowana również do realizacji innych zadań, niezwiązanych z interfejsem użytkownika.


3.1 Interfejs IApplication

Interfejs IApplication jest podstawowym mechanizmem interakcji skryptu ze środowiskiem aplikacji Asix.Evo. Interfejs udostępnia różnorodne usługi. Część ma znaczenie czysto informacyjne. Inne służą do organizacji pracy skryptu. Interfejs służy także do tworzenia innych obiektów, które pozwalają na dostęp do takich danych aplikacji jak wartości zmiennych procesowych, czy stan alarmów.

Referencja do obiektu realizującego interfejs IApplication przekazywana jest do skryptu w momencie wywołania funkcji Initialize skryptu


3.1.1.1. ApplicationAddonsDirectory

string ApplicationAddonsDirectory { get; }

ReadOnly Property ApplicationAddonsDirectory As String

Właściwość zwraca pełną ścieżkę dostępu do katalogu, w którym znajdują się wszystkie pliki rozszerzeń programowych aplikacji.


3.1.1.2. ApplicationDirectory

string ApplicationDirectory { get; }

ReadOnly Property ApplicationDirectory As String

Właściwość zwraca pełną ścieżkę dostępu do katalogu definicyjnego aplikacji. Jeżeli skrypt wymaga do pracy plików z dodatkowymi parametrami, to zaleca się, żeby były one przechowywane w katalogu definicyjnym aplikacji.


3.1.1.3 ApplicationName

string ApplicationName { get; }

ReadOnly Property ApplicationName As String

Właściwość zwraca nazwę aplikacji zdefiniowaną w ustawieniach stanowiska.


3.1.1.4 ApplicationWorkingDirectory

string ApplicationWorkingDirectory { get; }

ReadOnly Property ApplicationWorkingDirectory As String

Właściwość zwraca pełną ścieżkę dostępu do katalogu roboczego aplikacji. Jeżeli wynikiem działania skryptu jest tworzenie i zapis informacji do plików, to zaleca się żeby były one zapisywane w katalogu roboczym aplikacji.


Asalert

3.1.1.5 Asalert

AsalertAccess Asalert { get; }

ReadOnly Property Asalert As AsalertAccess

Właściwość zwraca referencję do obiektu klasy AsalertAccess, służącego do komunikacji z serwerem programu AsAlert. Zwrócony obiekt pozwala na wykonanie operacji wysłania alertu przy pomocy sms’u lub email’a.


AsixDataServerStarted

3.1.1.6 AsixDataServerStarted

bool AsixDataServerStarted { get; }

ReadOnly Property AsixDataServerStarted As Boolean

Właściwość zwraca informację, czy Serwer Danych został już uruchomiony. Właściwość może być użyta do kontrolowania, w trakcie startu aplikacji, czy system odczytu danych procesowych został w pełni uruchomiony.


3.1.1.5 CurrentApplicationLanguage

3.1.1.7 CurrentApplicationLanguage

string CurrentApplicationLanguage { get; }

ReadOnly Property CurrentApplicationLanguage As String

Właściwość zwraca nazwę języka, w którym aplikacja aktualnie pracuje. Nazwy języka są dwuliterowych skrótami, np. pl dla języka polskiego, en dla języka angielskiego.


3.1.1.6 CurrentStationName

3.1.1.8 CurrentStationName

string CurrentStationName { get; }

ReadOnly Property CurrentStationName As String

Właściwość zwraca nazwę stanowiska, w kontekście którego aplikacja jest wykonywana.


3.1.1.7 CurrentUserId

3.1.1.9 CurrentUserId

string CurrentUserId { get; }

ReadOnly Property CurrentUserId As String

Właściwość zwraca identyfikator aktualnie zalogowanego użytkownika.


3.1.1.8 CurrentUserName

3.1.1.10 CurrentUserName

string CurrentUserName { get; }

ReadOnly Property CurrentUserName As String

Właściwość zwraca nazwę aktualnie zalogowanego użytkownika.


3.1.1.9 CurrentUserRoles

3.1.1.11 CurrentUserRoles

string CurrentUserRoles { get; }

ReadOnly Property CurrentUserRoles As String

Właściwość zwraca nazwy wszystkich ról, które pełni aktualnie zalogowany użytkownik. Nazwy ról zwracane są w postaci pojedynczego tekstu, w którym poszczególne nazwy oddzielone są przecinkami. Jeżeli wymagane jest jedynie sprawdzenie, czy użytkownik pełni konkretną rolę, to łatwiejsze w użyciu jest zastosowanie funkcji HasRole.


3.1.1.10 ProgramVersion

3.1.1.12 ProgramVersion

string ProgramVersion { get; }

ReadOnly Property ProgramVersion As String

Właściwość zwraca numer wersji program AsixEvo. Numer wersji zwracany jest w postaci pojedynczego tekstu złożonego z czterech liczb rozdzielonych znakami kropki.


3.1.1.11 ScriptName

3.1.1.13 ScriptName

string ScriptName { get; }

ReadOnly Property ScriptName As String

Właściwość zwraca nazwę wykonywanego skryptu.


3.1.1.12 ExecutionContext

3.1.1.14 ExecutionContext

IContext ExecutionContext { get; }

ReadOnly Property ExecutionContext As IContext

Właściwość zwraca referencję do obiektu realizującego interfejs IContext. Interfejs ten zawiera właściwości, które określają kontekst wywołania skryptu. Kontekst wywołania jest szczególnie istotny w przypadku skryptów interakcyjnych uruchamianych w obsłudze zdarzeń obiektów wizualizacyjnych. Na podstawie kontekstu można np. pobrać nazwę zmiennej głównej obiektu.


3.1.1.13 ScriptSettings

3.1.1.15 ScriptSettings

IScriptSettings ScriptSettings { get; }

ReadOnly Property ScriptSettings As IScriptSettings

Właściwość zwraca referencję do obiektu realizującego interfejs IScriptSettings. Interfejs ten pozwala na określenie, w jaki sposób program główny kontroluje pracę i uruchamianie skryptu. W szczególności dotyczy to sposobu reakcji na błąd skryptu.


3.1.2.1 ApplicationText

string ApplicationText(string aTextId);

Function ApplicationText (ByVal aTextId As String) As String

Funkcja zapewnia wsparcie dla aplikacji wielojęzycznych. Zwraca napis z puli napisów aplikacji. Zwracany jest napis o identyfikatorze podanym w parametrze aTextId w wersji językowej zgodnej z aktualnym jezykiem pracy aplikacji.


3.1.2.2 CreateThread

Thread CreateThread(ThreadStart aThreadFunction);

Function CreateThread (ByVal aThreadFunction As System.Threading.ThreadStart) As System.Threading.Thread

Funkcja tworzy nowy wątek wykonawczy skryptu. Parametr aThreadFunction określa funkcję, która zostanie wykonana w nowym wątku. Funkcja wątku musi być zgodna z systemowym delegatem ThreadStart. Funkcja CreateThread zwraca systemowy obiekt klasy Thread, za pośrednictwem którego można kontrolować pracę skryptu.

W skryptach Asix.Evo zalecane jest tworzenie wątków za pośrednictwem funkcji CreateThread, zamiast bezpośrednich metod platformy .Net.

Przykład:

  C#

void ThreadFnc()

{

//

// kod wątku

//

}

public bool Initialize(string[] aParameters, IApplication aApplication)
{

   Thread t1 = aApplication.CreateThread(ThreadFnc);

          t1.Start();

   return false;
}

                VB

Sub ThreadFun()

'

' kod wątku

'

End Sub

Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

IApplication) As Boolean Implements IScript.Initialize

   Dim t1 As System.Threading.Thread

   t1 = aApplication.CreateThread(AddressOf ThreadFun)

   t1.Start()

   Return False

End Function

Funkcja ThreadFnc stanowi kod wątku. Wywołanie CreateThread tworzy wątek, a funkcja Start obiektu Thread uruchamia wątek.


3.1.2.3 ExecuteAction

bool ExecuteAction(string aAction);

Function ExecuteAction (ByVal aAction As String) As Boolean

Funkcja uruchamia akcję operatorską określoną parametrem aAction. Funkcja zwraca wartość false, gdy wystąpił błąd wykonania akcji.

Funkcja ExecuteAction rozszerza możliwości skryptów Asix.Evo o pełny zestaw operacji realizowanych w aplikacjach przy pomocy akcji operatorskich. Należy jednak zwrócić uwagę, że niektóre akcje wykonane w kontekście skryptu rezydentnego mogą mieć niekorzystne działanie. Na przykład, wykonanie akcji OpenWindow w przypadkowej chwili czasu może stanowić zaskoczenie dla użytkownika.


3.1.2.4 GetAlarm

IAlarm GetAlarm(string aAlarmName);

IAlarm GetAlarm(string aDomainName, string aAlarmName);

Function GetAlarm (ByVal aAlarmName As String) As IAlarm

Function GetAlarm (ByVal aDomain As String, ByVal aAlarmName As String) As IAlarm

Funkcja zwraca referencję do obiektu realizującego interfejs IAlarm dla alarmu o identyfikatorze określonym przez parametr aAlarmName z domeny o nazwie aDomain. Wersja wywołania bez podania nazwy domeny dotyczy domeny domyślnej (pierwszej zdefiniowanej) aplikacji.

Interfejs IAlarm pozwala na uzyskanie informacji na temat definicji alarmu i jego aktualnego stanu. Pozwala też na kontrolę stanu alarmu: zgłaszanie, kończenie i potwierdzanie alarmu.


3.1.2.5 GetAlarmDomainController

string[] GetAlarmDomainController(string aDomain);

Function GetAlarmDomainController (ByVal aDomain As String) As String()

Funkcja zwraca nazwę stanowiska aktywnego kontrolera domenie alarmowej określonej parametrem aDomain. Jeżeli nazwa domeny jest pusta, to wywołanie dotyczy domeny domyślnej (pierwszej zdefiniowanej) aplikacji.


3.1.2.6 GetAlarmDomains

string[] GetAlarmDomains();

Function GetAlarmDomains () As String()

Funkcja zwraca tablicę nazw wszystkich aktywnych domen alarmowych zdefiniowanych w aplikacji.


3.1.2.7 GetAlarmDomainStationMode

AlarmStationMode GetAlarmDomainStationName(string aDomain);

Function GetAlarmDomainStationName (ByVal aDomain As String) As AlarmStationMode

Funkcja zwraca aktualny tryb pracy systemu alarmów w domenie alarmowej określonej parametrem aDomain. Jeżeli nazwa domeny jest pusta, to wywołanie dotyczy domeny domyślnej (pierwszej zdefiniowanej) aplikacji.

Typ wyliczeniowy AlarmStationMode może przyjmować następujące wartości: ActiveController, PasiveController, Terminal i Undetermined. Tryb Undetermined jest trybem przejściowym, który może zostać zwrócony w stanach nieustalonych, np. w trakcie uruchamiania domeny.


3.1.2.8 GetActiveAlarms

string[] GetActiveAlarms(string aDomain);

Function GetActiveAlarms (ByVal aDomain As String) As String()

Funkcja zwraca tablicę identyfikatorów wszystkich aktualnie aktywnych alarmów w domenie alarmowej określonej parametrem aDomain. Jeżeli nazwa domeny jest pusta, to wywołanie dotyczy domeny domyślnej (pierwszej zdefiniowanej) aplikacji.


GetChannelState

3.1.2.9 GetChannelState

ChannelState GetChannelState(string aChannelName);

Function GetChannelName (ByVal aChannelName As String) As ChannelState

Funkcja zwraca aktualny status pracy kanału komunikacyjnego o nazwie podanej w parametrze aChannelName.

Typ wyliczeniowy ChannelState może przyjmować następujące wartości:

Correct - Kanał pracuje poprawnie

Initializing - Inicjalizacja kanału

MainChannelCommunicationError - Błąd komunikacji

MainChannelCommunicationErrorRedundantCommunication - Błąd komunikacji redundantnej

ControllerSTOP - Stan STOP sterownika

TempraryOff - Tymczasowo wyłączony

RedundantEvoDriver - W kanale Asix.Evo jest aktywny drajwer redundantny

OtherError - Inny błąd kanału

Unknown Channel - Nieznany kanał

Undetermined - Nieokreślony stan kanału


3.1.2.9 GetDefinedAlarms

3.1.2.10 GetDefinedAlarms

string[] GetDefinedAlarms(string aDomain);

Function GetDefinedAlarms (ByVal aDomain As String) As String()

Funkcja zwraca tablicę identyfikatorów wszystkich alarmów zdefiniowanych w domenie alarmowej określonej parametrem aDomain. Jeżeli nazwa domeny jest pusta, to wywołanie dotyczy domeny domyślnej (pierwszej zdefiniowanej) aplikacji.


3.1.2.10 GetTrendPatternPoints

3.1.2.11 GetTrendPatternPoints

TrendPatternPoint[] GetTrendPatternPoints(string aPatternName);

Function GetTrendPatternPoints(ByVal aPatternName As String) As TrendPatternPoint()

Funkcja zwraca tablicę punktów dla przebiegu wzorcowego o nazwie podanej w parametrze aPatternName.

Funkcja używana w skryptach, których zadaniem jest transfer przebiegu krzywej wzorcowej do sterownika.


3.1.2.11 GetVariable

3.1.2.12 GetVariable

IVariable GetVariable(string aVarName, bool aRefresh, bool aWithTimeStampsEvent);

IVariable GetVariable(string aVarName, bool aRefresh);

Function GetVariable(ByVal aVarName As String, ByVal aRefresh As Boolean) As IVariable

Function GetVariable(ByVal aVarName As String, ByVal aRefresh As Boolean, ByVal aWithTimeStampsEvent As Boolean) As IVariable

Funkcja zwraca referencję do obiektu realizującego interfejs IVariable dla zmiennej o nazwie określonej przez parametr aVarName. Parametr aRefresh określa, czy należy rozpocząć odświeżanie(okresowy odczyt) wartości zmiennej. Odświeżanie należy włączyć w przypadku monitorowania zmian wartości bieżącej zmiennej. Jeżeli skrypt będzie korzystał tylko z danych archiwalnych lub jedynie sterował wartością zmiennej, to włączenie odświeżania jest zbędne.

Parametr aWithTimeStampsEvent określa w jaki sposób wywoływana będzie funkcja monitorowania wartości zmiennych (deklarowana metodą RegisterStateEvent interfejsu IVariable). Wartość false lub brak parametru oznacza, że funkcja moniotorowania będzie wykonywana tylko wtedy, gdy zmieni się wartość lub status zmiennej. Wartość true oznacza, że kontrolowane będą także zmiany stempla czasu wartości.

Interfejs IVariable pozwala na uzyskanie informacji na temat definicji zmiennej oraz jej aktualnej wartości. Pozwala też na odczyt wartości archiwalnych oraz udostępnia metody zapisu wartości zmiennej.


GetVariableNames

3.1.2.13 GetVariableNames

String[] GetVariableNames(string aAttributeName, string aAttributeValue);

Function GetVariableNames(ByVal aAttributeName As String, ByVal aAttributeValue As String) As String()

Funkcja zwraca tablicę nazw wszystkich zmiennych, dla których atrybut o nazwie podanej w parametrze aAttributeName jest zgodny z wartością poodaną w parametrze aAttributeValue. W parametrze aAttributeValue można stosować znaki specjalne * i ?.

Przykład:

C#

sring[] n = aApplication.GetVariableNames("Channel", "K1");

VB

Dim n As String() = aApplication.GetVariableNames("Channel", "K1")

Powyższe wywołanie zwraca tablicę nazw wszystkich zmiennych z kanału komunikacyjnego o nazwie K1.


GetVariableValue

3.1.2.14 GetVariableValue

VariableState GetVariableValue(string aVariableName, bool aForceRead);

Function GetVariableValue(ByVal aVariableName As String, ByVal aForceRead As Boolean) As VariableState

Funkcja zwraca obiekt klasy VariableState z bieżąca wartością zmiennej o nazwie podanej w parametrze aVariableName. Wartość false parametru aForceRead oznacza, że zwrócona wartość pochodzi z ostatniego planowego odświeżenia wartości zmiennej. Wartość true powoduje bezpośredni odczyt aktualnej wartości zmiennej w chwili wykonania funkcji.


3.1.2.12 GlobalProperty

3.1.2.15 GlobalProperty

object GlobalProperty(string aPropertyName);

Function GlobalProperty (ByVal aPropertyName As String) As Object

Funkcja zwraca definicję właściwości globalnej aplikacji o nazwie określonej parametrem aPropertyName.


3.1.2.13 HasRole

3.1.2.16 HasRole

bool HasRole(string aRoleName);

Function HasRole (ByVal aRoleName As String) As Boolean

Funkcja zwraca wartość logiczną, która określa, czy aktualnie zalogowany użytkownik pełni rolę o nazwie przekazanej w parametrze aRoleName.


OPCTime

3.1.2.17 OPCTime

DateTime OPCTime(string aOPCTimeString);

DateTime GetVariable(string aOPCTimeString, DateTime aBaseTime);

Function OPCTime(ByVal aOPCTimeString As String) As Date

Function OPCTime (ByVal aOPCTimeString As String, ByVal aBaseTime As Date) As Date

Funkcja zwraca chwilę czasu wyliczoną na podstawie czasu bazowego i przesunięcia określonego wyrażeniem formatującym OPC. Czas bazowy jest określony parametrem aBaseTime lub jest czasem aktualnym dla wywołania jednoargumentowego.

Przesunięcie przekazywane w parametrze aOPCTimeString opisane jest rozszerzonym wyrażeniem formatującym OPC postaci:

[NOW|SECOND|MINUTE|HOUR|DAY|WEEK|MONTH|YEAR][cykl[/przesunięcie]] [[+|-][liczba][Y|MO|W|D|H|M|S]...]

Pierwsza część wyrażenia określa początkowe przesunięcie, np. HOUR początek godziny. Klauzule cykl i przesunięcie pozwalają na implementacje cykli, np. HOUR8/6 pozwala na wyliczenie początku 8-godzinnej zmiany, gdzie pierwsza zmiana zaczyna się o godzinie 6. Końcowa część wyrażenia pozwala dodatkowo przesunąć czas, np. HOUR-15M , oznacza 15 minut przed początkiem godziny.


RegisterAlarmDomainEvents

3.1.2.18 RegisterAlarmDomainEvents

IAlarmEventInfo RegisterAlarmDomainEvents(string aDomain, AlarmEvent aFunction, AlarmDomainEvents aEvent);

Function RegisterAlarmDomainEvents(ByVal aDomain As String, ByVal aFunction As AlarmEvent, ByVal aEvent As AlarmDomainEvents) As IAlarmEventInfo

Funkcja służy do zarejestrowania funkcji zwrotnej, która będzie wywoływana przy każdym zdarzeniu związanym ze zmianą stanu domeny. Parametr aEvent określa rodzaj zdarzeń, które należy monitorować. Typ wyliczeniowy AlarmDomainEvents przybiera następujące wartości: AlarmBegin (wykrycie początku alarmu), AlarmEnd (wykrycie końca alarmu), AlarmManagement (zmiana stanu wynikająca z działań operatora, np. potwierdzenia alarmu), DomainStart (uruchomienie pracy domeny), DomainStop (zatrzymanie pracy domeny), All (wszystkie typy zdarzeń). Możliwe jest łączenie typów zdarzeń operatorem sumy logicznej.

Parametr aFunction określa funkcję monitorującą stan alarmu – musi ona być zgodna z delegatem AlarmEvent.

delegate void AlarmEvent(string aDomain, string aAlarm, AlarmState aAlarmState, AlarmEventType aEventType);

Delegate Sub AlarmEvent(ByVal aDomain As String, ByVal aAlarm As String, ByVal aAlarmState As AlarmState ,ByVal aEventType As AlarmEventType).

W momencie wywołania funkcji monitorującej przekazywane są do niej trzy parametry. Parametry aDomain i aAlarm określają odpowiednio nazwę domeny i identyfikator alarmu, którego wywołanie funkcji zwrotnej dotyczy. Parametr aAlarmState przekazuje obiekt, z którego można odczytać aktualny stan alarmu. Parametr aEventType określa rodzaj zdarzenia. Typ wyliczeniowy AlarmEventType przybiera następujące wartości: AlarmBegin (wykrycie początku alarmu) , AlarmEnd (wykrycie końca alarmu), AlarmManagement (zmiana stanu wynikająca z działań operatora, np. potwierdzenia alarmu), DomainStart (uruchomienie pracy domeny), DomainStop (zatrzymanie pracy domeny).

Metoda RegisterAlarmDomainEvents zwraca obiekt interfejsu IAlarmEvcentInfo. Obiekt ten udostępnia jedną metodę UnregisterStateEvent. Służy ona do wyrejestrowania funkcji monitorującej.

Przykład:

C#

IAlarmEventInfo alarmInfo;

IApplication application;

public bool Initialize(string[] aParameters, IApplication aApplication)

{

application = aApplication;

alarmInfo = aApplication.RegisterAlarmDomainEvents("DemoB1", AlarmFun,

AlarmDomainEvents.AlarmBegin | AlarmDomainEvents.AlarmEnd);

return false;

}

public void FinalizeScript()

{

if (alarmInfo != null)

alarmInfo.UnregisterStateEvent();

}

void AlarmFun(string aDoamin,string aId, AlarmState aState, AlarmEventType aType)

{

if (aType == AlarmEventType.AlarmBegin)

application.ReportMessage(EvoMessageType.Info,

"Wykryty początek alarmu " + aId + ", czas detekcji " +

aState.BeginDetectionTimeStamp);

else if (aType == AlarmEventType.AlarmEnd)

application.ReportMessage(EvoMessageType.Info,

"Wykryty koniec alarmu " + aId + ", czas detekcji " +

aState.EndDetectionTimeStamp);

}

VB

Dim alarmInfo As IAlarmEventInfo

Dim application As IApplication

Public Function Initialize(ByVal aParameters() As String, ByVal aApplication _

As IApplication) As Boolean Implements IScript.Initialize

application = aApplication

alarmInfo = aApplication.RegisterAlarmDomainEvents("DemoB1", _

AddressOf AlarmFun, _

AlarmDomainEvents.AlarmBegin Or AlarmDomainEvents.AlarmEnd)

Return False

End Function

Public Sub FinalizeScript() Implements IScript.FinalizeScript

If Not alarmInfo Is Nothing

alarmInfo.UnregisterStateEvent()

End If

End Sub

Sub AlarmFun(aDomain As String, aId As String, aState As AlarmState, _

aType As AlarmEventType)

If aType = AlarmEventType.AlarmBegin

application.ReportMessage(EvoMessageType.Info, _

"Wykryty początek alarmu " + aId + ", czas detekcji " + _

aState.BeginDetectionTimeStamp)

Else If aType = AlarmEventType.AlarmEnd

application.ReportMessage(EvoMessageType.Info, _

"Wykryty koniec alarmu " + aId + ", czas detekcji " + _

aState.EndDetectionTimeStamp)

End If

End Sub

Powyższy kod rejestruje funkcję monitorującą w domenie DemoB1 dla zdarzeń początków i końców alarmów. Funkcja monitorująca zapisuje w logu komunikatów informację o każdym rozpoczętym i zakończonym alarmie.


3.1.2.14 RegisterTimeEvent

3.1.2.19 RegisterTimeEvent

IEventInfo RegisterTimeEvent(SimpleEvent aFunction, TimeSpan aPeriod, TimeSpan aAlign);

Function RegisterTimeEvent(ByVal aFunction As SimpleEvent, ByVal aPeriod As System.TimeSpan, ByVal aAlign As System.TimeSpan) As IEventInfo

Funkcja służy do zarejestrowania funkcji zwrotnej, która będzie cyklicznie wywoływana w określonych odstępach czasu. Parametr aFunction określa funkcję, która będzie wykonywana okresowo – musi ona być zgodna z delegatem SimpleEvent.

delegate void SimpleEvent();

Delegate Sub SimpleEvent()

Parametr aPeriod określa okres czasu z jakim funkcja zwrotna będzie wykonywana. Parametr aAlign określa wyrównanie czasu uruchomienia względem początku doby. Jeżeli parametr jest mniejszy niż zero (np. TimeSpan.FromSeconds(-1) ), to wyrównanie nie jest wykonywane. Jeżeli aAlign jest równy zero, to funkcja zwrotna będzie wywoływana co okres aPeriod, zaczynając od godziny 00:00. Jeżeli aAlign jest większy niż zero, to funkcja zwrotna będzie wywoływana co okres aPeriod, zaczynając od godziny 00:00 + aAlign.

Funkcja RegisterTimeEvent zwraca wartość, którą można użyć do wyrejestrowania funkcji zwrotnej przy pomocy metody UnregisterEvent.

Przykład:

  C#

void CallbackFun()

{

//

// kod funkcji zwrotnej

//

}

public bool Initialize(string[] aParameters, IApplication aApplication)
{

   aApplication.RegisterTimeEvent(CallbackFun, TimeSpan.FromHours(1),

                                  TimeSpan.FromMinutes(15));

   return false;
}

                VB

Sub CallbackFun()

'

' kod funkcji zwrotnej

'

End Sub

Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

IApplication) As Boolean Implements IScript.Initialize

   aApplication.RegisterTimeEvent(AddressOf CallbackFun, TimeSpan.FromHours(1),_

                                  TimeSpan.FromMinutes(15))

   Return False

End Function

Funkcja zwrotna CallbackFun będzie wykonywana co godzinę z przesunięciem 15 minut, czyli o godzinach 0:15, 1:15, 2:15 itd.


3.1.2.15 ReportMessage

3.1.2.20 ReportMessage

void ReportMessage(EvoMessageType aType, string aText);

Sub ReportMessage (ByVal aType As EvoMessageType, ByVal aText As String)

Funkcja zapisuje w aplikacyjnym logu komunikat o treści podanej w parametrze aText. Parametr aType określa ważność komunikatu. Wyliczeniowy typ EvoMessageType przyjmuje następujące wartości: Exception, Error, Warning, Info, Trace. Komunikaty typu Trace nie są wyświetlane w okienku komunikatów, są jedynie zapisywane w pliku logu.

Poziom raportowania pracy skryptu w logu komunikatów jest w gestii projektanta skryptu. Należy jednak pamiętać o dokładnym raportowaniu wszystkich błędów, które wystąpiły w trakcie pracy. Dotyczy to szczególnie skryptów rezydentnych.


3.1.2.18 RestartScript

3.1.2.21 RestartScript

void RestartScript();

Sub RestartScript()

Metoda pozwala na wykonanie pełnego restart skryptu. Należy stosować wtedy, gdy własny kod kontrolny skryptu stwierdzi jego nieprawidłowe działanie wymagające restartu. Niezależnie od tego mechanizmu, w przypadku niekontrolowanego upadku skrytpu, możliwy jest jego automatyczny restart (jeżeli została ustawiona właściwość RestartIfFailed interfejsu IScriptSettings).


3.1.2.19 SetVariableBits

3.1.2.22 SetVariableValue

bool SetVariableValue(string aVariableName, object aValue);

Function SetVariableValue(ByVal aVariableName As String, ByVal aValue As Object) As Boolean

Funkcja powoduje ustawienia wartości zmiennej o nazwie podanej w parametrze aVariableName, na nową wartość podaną w parametrze aValue. Stempel czasu zmiennej zostanie ustawiony na chwilę bieżącą, a status na StatusOpc.Good.

Funkcja zwraca status przyjęcia operacji do realizacji.


3.1.2.16 Sleep

3.1.2.23 Sleep

void Sleep(TimeSpan aTimeSpan);

Sub Sleep (ByVal aTimeSpan As System.TimeSpan)

Funkcja zawiesza działanie bieżącego wątku skryptu na okres czasu podany w parametrze aTimeSpan. Funkcję należy stosować wszędzie tam, gdzie wymagane jest odczekanie na zajście jakiegoś zdarzenia lub upłynięcie określonego odcinka czasu. W żadnym przypadku nie należy stosować aktywnej pętli testującej warunki – prowadzi to do nadmiernego obciążenia procesora).

Przykład:

C#

       aApplication.Sleep(TimeSpan.FromSeconds(5));

                VB

       aApplication.Sleep(TimeSpan.FromSeconds(5))

Wywołanie zawiesza działania skryptu na 5 sekund.


3.1.2.17 TerminateScript

3.1.2.24 TerminateScript

void TerminateScript(bool aWithFinalize);

Sub TerminateScript (ByVal aWithFinalize As Boolean)

Wywołanie funkcji powoduje zakończenie pracy skryptu. Parametr aWithFinalize określa, czy w trakcie procesu rozładowania skryptu należy wykonać metodę Finalize skryptu.

Funkcja TerminateScript jest używana tylko w szczególnych przypadkach. Skrypty interakcyjne (jednorazowe) zazwyczaj kończone są przez wyjście z funkcji Initialize z wartością zwracaną true. Skrypty rezydentne są kończone automatycznie w momencie końca pracy aplikacji.


3.1.2.18 UnregisterEvent

3.1.2.25 UnregisterEvent

void UnregisterEvent(IEventInfo aCallbackInfo);

Sub UnregisterEvent(ByVal aCallbackInfo As IEventInfo)

Wyrejestrowanie funkcji uruchamianej czasowo, która została wcześniej zarejestrowana przy pomocy funkcji RegisterTimeEvent. Jako parametr aCallbackInfo należy przekazać wartość zwróconą w momencie rejestrowania funkcji.


Interfejs IContext

3.2 Interfejs IContext

Interfejs IContext zawiera właściwości, które określają kontekst wywołania skryptu. Kontekst wywołania jest szczególnie istotny w przypadku skryptów interakcyjnych uruchamianych w obsłudze zdarzeń obiektów wizualizacyjnych. Interfejs pozwala uzależnić działanie skryptu od sposobu jego uruchomienia.

Referencję do interfejsu IContext można uzyskać poprzez odczyt właściwości ExecutionContext interfejsu IApplication.


3.2.1.1 Diagram

string Diagram { get; }

ReadOnly Property Diagram As String

Właściwość zwraca nazwę diagramu, w kontekście którego skrypt został uruchomiony.


3.2.1.2 DiagramObject

string DiagramObject { get; }

ReadOnly Property DiagramObject As String

Właściwość zwraca nazwę obiektu wizualizacyjnego, w kontekście którego skrypt został uruchomiony.


3.2.1.3 IsWebBrowser

bool IsWebBrowser { get; }

ReadOnly Property IsWebBrowser As Boolean

Właściwość zwraca informację, czy aplikacja pracuje w środowisku przeglądarki.


3.2.1.4 MainVariable

string MainVariable { get; }

ReadOnly Property MainVariable As String

Właściwość zwraca nazwę głównej zmiennej obiektu wizualizacyjnego, w kontekście którego skrypt został uruchomiony.


3.2.1.5 ScriptStartTime

DateTime ScriptStartTime { get; }

ReadOnly Property ScriptStartTime As Date

Właściwość zwraca czas momentu uruchomienia skryptu.


3.2.1.6 WebServerAddress

string WebServerAddress { get; }

ReadOnly Property WebServerAddress As String

Właściwość zwraca adres serwera WWW, z którego została załadowana aplikacja przeglądarkowa.


Interfejs IScriptSettings

3.3 Interfejs IScriptSettings

Interfejs IScirptSettings zawiera właściwości, które określają sposobu kontroli pracy skryptu przez program główny.

Referencję do interfejsu IScriptSettings można uzyskać poprzez odczyt właściwości ScriptSettings.


AllowMultipleInstances

3.3.1.2 RestartIfFailed

bool
 RestartIfFailed { get;
 set;
 }

Property RestartIfFailed As Boolean

Właściwość określa sposób reakcji na błąd wykonania skryptu. Wartość true oznacza, że w przypadku upadku skryptu zostanie on automatycznie ponownie uruchomiony. Wartość domyślna jest równa false.

Typowo, właściwość jest ustawiana na true dla skryptów autonomicznych po zakończeniu fazy inicjalizacji.


Interfejs IVariable

3.4 Interfejs IVariable

Interfejs IVariable pozwala na uzyskanie informacji dotyczących definicji zmiennej oraz jej aktualnej wartości, odczyt wartości archiwalnych, aktywne monitorowanie zmian wartości bieżącej oraz udostępnia metody zapisu wartości zmiennej.

Referencję do interfejsu IVariable dla wybranej zmiennej alarmu można uzyskać poprzez wywołanie funkcji GetVariable z interfejsu IApplication.


3.3.1.1 Name

3.4.1.1 Name

string Name { get; }

ReadOnly Property Name As String

Właściwość zwraca nazwę zmiennej procesowej kontrolowanej przez posiadaną referencję do interfejsu IAlarm.


3.3.1.2 IsRefreshed

3.4.1.2 IsRefreshed

bool IsRefreshed { get; }

ReadOnly Property IsRefreshed As Boolean

Właściwość zwraca informację, czy wykonywane jest cykliczne odświeżanie wartości zmiennej. Tryb odświeżania deklarowany jest w momencie tworzenia interfejsu IVariable funkcją GetVariable interfejsu IApplication.


3.3.1.3 VariableState

3.4.1.3 VariableState

VariableState VariableState { get; }

ReadOnly Property VariableState As VariableState

Właściwość zwraca obiekt klasy VariableState, z którego można odczytać aktualną wartość i status zmiennej procesowej. Wartość zmiennej pochodzi z chwili ostatniego odświeżenia zmiennej. Okres odświeżania jest określony w definicji zmiennej procesowej.


3.3.2.1 OrderArcData

3.4.2.1 OrderArcData

IArcQueryResult OrderArcData(ArcQuery aQuery);

Function OrderArcData (ByVal aQuery As ArcQuery) As IArcQueryResult

Funkcja służy do odczytu danych archiwalnych zmiennej procesowej. Obiekt klasy ArcQuery przekazywany jako parametr aQuery określa parametry odczytu, w szczególności okres czasu i sposób agreagacji. Funkcja OrderArcData jedynie inicjuje proces odczytu danych historycznych. Zwracany obiekt interfejsu IArcQueryResult służy do kontroli procesu pozyskania danych oraz odczytu danych wynikowych.

Przykład:

C#

       public bool Initialize(string[] aParameters, IApplication aApplication)

       {

          IVariable iv = aApplication.GetVariable("A004", false);

IArcQueryResult qr = iv.OrderArcData(new ArcQuery(DateTime.Today, DateTime.Now,

                                     "average", TimeSpan.FromMinutes(15)));

          if (qr.ResultStatus == ArcResultStatus.Processing)

   qr.Wait();

          if (qr.ResultStatus == ArcResultStatus.Error)

             aApplication.ReportMessage(EvoMessageType.Error, "OrderArcData error: " +

                                         qr.ErrorDescription);

          else

          {

              foreach (ArcVariableState v in qr.Values)

                aApplication.ReportMessage(EvoMessageType.Info, v.TimeStamp.ToString() +

 ": " + v.Value.ToString());

          }

          return true;

       }

                VB

Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

IApplication) As Boolean Implements IScript.Initialize

   Dim iv As IVariable

   iv = aApplication.GetVariable("A004", False)

   Dim qr As IArcQueryResult

   qr = iv.OrderArcData(New ArcQuery(Date.Today, Date.Now, _

        "average", TimeSpan.FromMinutes(15)))

   If (qr.ResultStatus = ArcResultStatus.Processing)

      Qr.Wait()

   End If

   If (qr.ResultStatus = ArcResultStatus.Error)

      aApplication.ReportMessage(EvoMessageType.Error, _

                       "OrderArcData error: " + qr.ErrorDescription)

   Else

      For Each v As ArcVariableState In qr.Values

         aApplication.ReportMessage(EvoMessageType.Error, _

                          v.TimeStamp.ToString() + ": " + v.Value.ToString())

      Next v

   End If

   Return True

End Function

Przekazany w wywołaniu metody OrderArcData obiekt klasy ArcQuery powoduje odczyt 15-minutowych wartości średnich z okresu od początku dnia do chwili bieżącej. Po inicjacji odczytu następuje oczekiwanie na koniec operacji poprzez wywołanie funkcji Wait obiektu IArcQueryResult, zwróconego w wyniku wykonania metody OrderArcData. Jeżeli odczyt zakończył się poprawnie, to do logu komunikatów zapisywane są wszystkie wartości archiwalne, które zostały zwrócone poprzez właściwość Values obiektu klasy IArcQueryResult.


3.3.2.2 Read

3.4.2.2 Read

VariableState Read();

Function Read () As VariableState

Funkcja zwraca obiekt klasy VariableState, z którego można odczytać aktualną wartość i status zmiennej procesowej. Funkcja wymusza rzeczywisty odczyt zmiennej, wartość zmiennej pochodzi z momentu wykonania funkcji.

Czas wykonania funkcji zależy od czasu wykonania operacji odczytu wartości zmiennej ze źródła danych.


3.3.2.3 RegisterStateEvent

void RegisterStateEvent(VariableEvent aFunction);

Sub RegisterStateEvent(ByVal aFunction As VariableEvent)

Funkcja służy do zarejestrowania funkcji zwrotnej, która będzie wywoływana przy każdej zmianie wartości, statusu lub czasu kontrolowanej zmiennej. Parametr aFunction określa funkcję monitorującą stan zmiennej – musi ona być zgodna z delegatem VariableEvent.

delegate void VariableEvent(string aVariableName, VariableState aVariableState);

Delegate Sub VariableEvent(ByVal aVariableName As String, ByVal aVariableState As VariableState)

W momencie wywołania funkcji monitorującej przekazywane są do niej dwa parametry. Parametr aVariableName określa nazwę zmiennej. Możliwe jest podłączenie tej samej funkcji monitorującej do wielu zmiennych, a poprzez parametr aVariableName można rozróżnić, której zmiennej wywołanie dotyczy. Parametr aVariableState przekazuje obiekt, z którego można odczytać aktualny stan zmiennej.

Do poprawnego działania funkcji monitorującej wymagane jest włączenie odświeżania zmiennej w momencie tworzenia obiektu interfejsu IVariable. Funkcję monitorującą można wyrejestrować przy pomocy metody UnregisterStateEvent.

Przykład:

  C#

IApplication application;

void ValueFun(string aVariableName, VariableState aVariableState)

{

// kod funkcji zwrotnej

   application.ReportMessage(EvoMessageType.Info, aVariableName + " = " +

                             aVariableState.FormattedValue);

}

public bool Initialize(string[] aParameters, IApplication aApplication)
{

   application = aApplication;

   IVariable iv = aApplication.GetVariable("varTest", true);

   iv.RegisterStateEvent(ValueFun);

   return false;
}

 VB

Dim application As IApplication

Sub ValueFun(aVariableName As String, aVariableState As VariableState)

   ' kod funkcji zwrotnej

   application.ReportMessage(EvoMessageType.Info, aVariableName & _

" = " & aVariableState.FormattedValue)

End Sub

Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

IApplication) As Boolean Implements Initialize

   application = aApplication

   Dim iv As IVariable

   iv = application.GetVariable("varTest", True)

   iv.RegisterStateEvent(AddressOf ValueFun)

   Return False

End Function

Powyższy kod tworzy obiekt IVariable dla zmiennej varTest z włączonym odświeżaniem zmiennej. Następnie rejestrowana jest funkcja monitorująca ValueFun, która przy każdej zmienie stanu zmiennej zapisuje w logu komunikatów informację złożoną z nazwy zmiennej i jej aktualnej wartości.


3.3.2.4 SetVariableBits

bool SetVariableBits(long aValue, long aMask);

bool SetVariableValue(long aValue, long aMask, StatusOpc aStatus);

Function SetVariableBits(ByVal aValue As Long, ByVal aMask As Long) As Boolean

Function SetVariableBits(ByVal aValue As Long, ByVal aMask As Long, ByVal aStatus As Askom.Ascent.StatusOpc) As Boolean

Funkcja powoduje wysterowanie zmiennej procesowej na wartość podaną w parametrze aValue z dodatkowym maskowaniem zmienianych bitów przez parametr aMask. W pierwszej fazie wykonania odczytywana jest bieżąca wartość zmiennej, a następnie bity, którym w masce aMask odpowiada wartość 1, zmieniane są zgodnie z wartościami w parametrze aValue.

Wersja wywołania z parametrem aStatus dodatkowo ustawia nowy status zmiennej. Wersje bez parametru aStatus ustawiają zawsze status na StatusOpc.Good.

Funkcja zwraca wartość false w przypadku niepowodzenia. Ponieważ funkcja wykonywana jest w sposób asynchroniczny, to test poprawności dotyczy tylko spełnienia warunków wstępnych. W przypadku błędu komunikacji zostanie on zgłoszony w panelu komunikatów.


3.3.2.5 SetVariableValue

3.4.2.5 SetVariableValue

bool SetVariableValue(object aValue);

bool SetVariableValue(object aValue, StatusOpc aStatus);

Function SetVariableValue(ByVal aValue As Object) As Boolean

Function SetVariableValue(ByVal aValue As Object, ByVal aStatus As Askom.Ascent.StatusOpc) As Boolean

Funkcja powoduje wysterowanie zmiennej procesowej na wartość podaną w parametrze AValue.

Wersja wywołania z parametrem aStatus dodatkowo ustawia nowy status zmiennej. Wersje bez parametru aStatus ustawiają zawsze status na StatusOpc.Good.

Funkcja zwraca wartość false w przypadku niepowodzenia. Ponieważ funkcja wykonywana jest w sposób asynchroniczny, to test poprawności dotyczy tylko spełnienia warunków wstępnych. W przypadku błędu komunikacji zostanie on zgłoszony w panelu komunikatów.


3.3.2.6 UnregisterStateEvent

3.4.2.6 UnregisterStateEvent

void UnregisterStateEvent();

Sub UnregisterStateEvent()

Wyrejestrowanie funkcji monitorującej wartości zmiennej, która została wcześniej zarejestrowana przy pomocy funkcji RegisterStateEvent.


3.3.2.7 VariableAttribute

3.4.2.7 VariableAttribute

object VariableAttribute(string aAttributeName);

Function VariableAttribute (ByVal aAttributeName As String) As Object

Funkcja zwraca definicję atrybutu zmiennej procesowej o nazwie określonej parametrem aAttributeName.


Klasa VariableState

3.5 Klasa VariableState

Obiekt klasy VariableState pozwala na odczyt aktualnej wartości zmiennej procesowej, jej statusu oraz stempla czasu. Obiekty klasy VariableState tworzone są za pośrednictwem interfejsu IVariable, korzystając z właściwości VariableState lub funkcji Read. Dostarczane są także jako parametr funkcji monitorującej zmiany wartości zmiennej, rejestrowanej funkcją RegisterStateEvent interfejsu IVariable.


3.4.1.1 FormattedValue

3.5.1.1 FormattedValue

string FormattedValue { get; }

ReadOnly Property FormattedValue As String

Właściwość zwraca wartość tekstową zmiennej procesowej utworzoną na podstawie formatu zdefiniowanego w bazie definicji zmiennych.


3.4.1.2 IsBad

3.5.1.2 IsBad

bool IsBad { get; }

ReadOnly Property IsBad As Boolean

Właściwość określa, czy status wartości zmiennej jest niepoprawny.


3.4.1.3 IsGood

3.5.1.3 IsGood

bool IsGood { get; }

ReadOnly Property IsGood As Boolean

Właściwość określa, czy status wartości zmiennej jest poprawny.


3.4.1.4 IsUncertain

3.5.1.4 IsUncertain

bool IsUncertain { get; }

ReadOnly Property IsUncertain As Boolean

Właściwość określa, czy status wartości zmiennej jest niepewny.


3.4.1.5 RawValue

3.5.1.5 RawValue

object RawValue { get; }

ReadOnly Property RawValue As Object

Właściwość zwraca wartość surową zmiennej procesowej. Jest to oryginalna wartość zmiennej odczytana przez drajwer kanału komunikacyjnego, przed zastosowaniem funkcji przeliczającej zdefiniowanej w bazie zmiennych w atrybucie Funkcja przeliczająca odczytu.

UWAGA: w przypadku korzystania z kanału komunikacyjnego Asix, wartość właściwości jest już wstępnie przeliczona przez moduł komunikacyjny Asmen na podstawie atrybutu Funkcja przeliczająca.


3.4.1.6 Status

3.5.1.6 Status

public StatusOpc Status { get; }

ReadOnly Property Status As Askom.Ascent.StatusOpc

Właściwość zwraca szczegółowy status wartości zmiennej procesowej w konwencji statusu interfejsu komunikacyjnego OPC. Do prostych testów statusu zmiennej zalecane jest korzystanie z właściwości IsGood, IsBad i IsUncertain.


3.4.1.7 TimeStamp

3.5.1.7 TimeStamp

DateTime TimeStamp { get; }

ReadOnly Property TimeStamp As Date

Właściwość zwraca czas odczytu wartości zmiennej.


3.4.1.8 Value

3.5.1.8 Value

object Value { get; }

ReadOnly Property Value As Object

Właściwość zwraca wartość zmiennej procesowej po zastosowaniu wszystkich przeliczeń wynikających z definicji zmiennej w bazie definicji zmiennych.


Klasa ArcQuery

3.6 Klasa ArcQuery

Klasa ArcQuery służy do określenia parametrów odczytu wartości archiwalnych zmiennej procesowej. Obiekty ArcQuery używane są w wywołaniach metody OrderArcData interfejsu IVariable.


3.5.1 Konstruktor

ArcQuery (DateTime aStartTime, DateTime aEndTime)

Public Sub New(ByVal aStartTime As Date, ByVal aEndTime As Date)

Konstruktor tworzy obiekt parametrów dla zapytania dotyczącego odczytu danych surowych. Parametry aStartTime i aEndTime oznaczają kolejno początek i koniec okresu czasu, z jakiego dane należy odczytać.

ArcQuery ( DateTime aStartTime, DateTime aEndTime, string aAggregate, TimeSpan aAggregateInterval)

Public Sub New(ByVal aStartTime As Date, ByVal aEndTime As Date, ByVal aAggregate As String, ByVal aAggregateInterval As System.TimeSpan)

Konstruktor tworzy obiekt parametrów dla zapytania dotyczącego odczytu danych agregowanych. Parametry aStartTime i aEndTime oznaczają kolejno początek i koniec okresu czasu, z jakiego dane należy odczytać. Parametr aAggregate określa nazwę zastosowanego agregatu, a parametr aAggregateInterval okres jego wyliczania.

Zobacz też

Rodzaje agregatów danych archiwalnych - patrz >>


3.5.2.1 Aggregate

string Aggregate { get; }

ReadOnly Property Aggregate As String

Właściwość zwraca nazwę agregatu użytego w zapytaniu o dane archiwalne.


3.5.2.2 AggregateInterval

3.6.2.2 AggregateInterval

TimeSpan TimeStamp { get; }

ReadOnly Property AggregateInterval As System.TimeSpan

Właściwość zwraca okres wyliczania agregatu użyty w zapytaniu o dane archiwalne.


3.5.2.3 EndTime

3.6.2.3 EndTime

DateTime EndTime { get; }

ReadOnly Property EndTime As Date

Właściwość zwraca koniec okresu czasu, z którego dane archiwalne mają zostać odczytane.


3.5.2.4 ProcessedDataQuery

3.6.2.4 ProcessedDataQuery

bool ProcessedDataQuery { get; }

ReadOnly Property ProcessedDataQuery As Boolean

Właściwość zwraca informację, jakiego rodzaju danych archiwalnych zapytanie dotyczy. Wartość true oznacza odczyt danych agregowanych, a wartość false odczyt danych surowych.


3.5.2.5 StartTime

3.6.2.5 StartTime

DateTime StartTime { get; }

ReadOnly Property StartTime As Date

Właściwość zwraca początek okresu czasu, z którego dane archiwalne mają zostać odczytane.


Interfejs IArcQueryResult

3.7 Interfejs IArcQueryResult

Interfejs IArcQueryResult służy do kontroli wykonania operacji odczytu danych archiwalnych zainicjowanej metodą OrderArcData interfejsu IVariable. Właściwości i metody interfejsu pozwalają na sprawdzenie, czy i w jaki sposób operacja się zakończyła oraz udostępniają odczytane wartości.


3.6.1.1 ErrorDescription

3.7.1.1 ErrorDescription

string ErrorDescription { get; }

ReadOnly Property ErrorDescription As String

Właściwość zwraca tekst opisujący błąd odczytu danych archiwalnych (gdy właściwość ResultStatus jest równa ArcResultStatus.Error).


3.6.1.2 Query

3.7.1.2 Query

ArcQuery Query { get; }

ReadOnly Property Query As ArcQuery

Właściwość zwraca obiekt klasy ArcQuery, z którego można odczytać parametry odczytu danych archiwalnych, użyte w funkcji OrderArcData.


3.6.1.3 ResultStatus

3.7.1.3 ResultStatus

ArcResultStatus ResultStatus { get; }

ReadOnly Property ResultStatus As ArcResultStatus

Właściwość zwraca aktualny status wykonywania operacji odczytu danych archiwalnych. Typ wyliczeniowy ArcResultStatus może przyjmować następujące wartości:

  • Processing – odczyt danych jest w trakcie wykonywania

  • Ready – odczyt danych został zakończony poprawnie

  • Error – odczyt danych zakończył się błędem


3.6.1.4 Values

3.7.1.4 Values

ArcVariableState[ ] Values { get; }

ReadOnly Property ArcVariableState As ArcVariableState( )

Właściwość zwraca tablicę punktów przebiegu archiwalnego uzyskaną w wyniku wykonania funkcji OrderArcData.


3.6.1.5 VariableName

3.7.1.5 VariableName

string VariableName { get; }

ReadOnly Property VariableName As String

Właściwość zwraca nazwę zmiennej, dla której odczytywane są dane archiwalne.


3.6.2.1. CancelQuery

void CancelQuery( );

Sub CancelQuery ( )

Metoda CancelQuery pozwala na przerwanie wykonywanej operacji odczytu danych archiwalnych.


3.6.2.2 RegisterQueryResultEvent

void RegisterQueryResultEvent(ArcQueryResultEvent aFunction);

Sub RegisterQueryResultEvent(ByVal aFunction As ArcQueryResultEvent)

Funkcja służy do zarejestrowania funkcji zwrotnej, która zostanie wywoływana po zakończeniu operacji odczytu danych archiwalnych. Parametr aFunction określa funkcję zwrotną – musi ona być zgodna z delegatem ArcQueryResultEvent.

delegate void ArcQueryResultEvent(IArcQueryResult aQueryResult);

Delegate Sub ArcQueryResultEvent(ByVal aQueryResult As IArcQueryResult)

W parametrze aQueryResult do funkcji zwrotnej przekazywana jest referencja do interfejsu IArcQueryResult, w kontekście którego rejestracja została wykonana.

Funkcję oczekiwania na koniec odczytu można wyrejestrować przy pomocy metody UnregisterQueryResultEvent.

Przykład:

C#

IApplication application;

void ArcQueryFun(IArcQueryResult aQueryResult)

{

   if (aQueryResult.ResultStatus == ArcResultStatus.Error)

      application.ReportMessage(EvoMessageType.Error, "OrderArcData error: " +

                                aQueryResult.ErrorDescription);

   else

   {

      foreach (ArcVariableState v in aQueryResult.Values)

         application.ReportMessage(EvoMessageType.Error, v.TimeStamp.ToString() +

                            ": " + v.Value.ToString());

   }

   application.TerminateScript(true);

}

public bool Initialize(string[] aParameters, IApplication aApplication)

{

   application = aApplication;

   IVariable iv = aApplication.GetVariable("A004", false);

   IArcQueryResult qr = iv.OrderArcData(new ArcQuery(DateTime.Today,

       DateTime.Now,"average",TimeSpan.FromMinutes(15)));

   if (qr.ResultStatus == ArcResultStatus.Error)

      aApplication.ReportMessage(EvoMessageType.Error, "OrderArcData error: " +

                                qr.ErrorDescription);

   else

     qr.RegisterQueryResultEvent(ArcQueryFun);

   return false;

}

                VB

Dim application As IApplication

Sub QueryArcFun(aQueryResult As IArcQueryResult)

   If (aQueryResult.ResultStatus = ArcResultStatus.Error)

      application.ReportMessage(EvoMessageType.Error, _

                        "OrderArcData error: " + aQueryResult.ErrorDescription)

   Else

      For Each v As ArcVariableState In aQueryResult.Values

         application.ReportMessage(EvoMessageType.Error, _

v.TimeStamp.ToString() + ": " + v.Value.ToString())

      Next v

   End If

   application.TerminateScript(True)

End Sub

Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

IApplication) As Boolean Implements IScript.Initialize

   application = aApplication

   Dim iv As IVariable

   iv = aApplication.GetVariable("A004", False)

   Dim qr As IArcQueryResult

   qr = iv.OrderArcData(New ArcQuery(Date.Today, Date.Now, _

"average", TimeSpan.FromMinutes(15)))

   If (qr.ResultStatus = ArcResultStatus.Error)

      aApplication.ReportMessage(EvoMessageType.Error, _

"OrderArcData error: " + qr.ErrorDescription)

   Else

      qr.RegisterQueryResultEvent(AddressOf QueryArcFun)

   End If

   Return False

End Function

Przekazany w wywołaniu metody OrderArcData obiekt klasy ArcQuery powoduje odczyt 15-minutowych wartości średnich z okresu od początku dnia do chwili bieżącej. Jeżeli inicjacja odczytu wykonała się poprawnie, to rejestrowana jest funkcja ArcQueryFun, która zostanie wykonana po zakończeniu operacji. Wewnątrz funkcji zwrotnej ArcQueryFun wykonywany jest zapis do logu komunikatów wszystkich wartości archiwalnych, które zostały zwrócone poprzez właściwość Values obiektu klasy IArcQueryResult przekazanego w wywołaniu funkcji. Następnia praca skryptu zostaje zakónczona.


3.6.2.3 UnregisterQueryResultEvent

void UnregisterQueryResultEvent();

Sub UnregisterQueryResultEvent()

Wyrejestrowanie funkcji oczekującej na zakończenie operacji odczytu, która została wcześniej zarejestrowana przy pomocy funkcji RegisterQueryResultEvent.


3.6.2.4 Wait

bool Wait();

Function Wait() As Boolean

Funkcja zawiesza wykonywanie skryptu do momentu zakończenia realizacji operacji odczytu danych archiwalnych. Funkcja ma wbudowane 5-minutowe ograniczenie czasu oczekiwania. Jeżeli dane nie zostaną odczytane w tym czasie, to funkcja zwraca wartość false.

Alternatywą dla funkcji Wait jest użycie funkcji Sleep interfejsu IApplication połączone z monitorowaniem wartości statusu QueryResult.


Klasa ArcVariableState

3.8 Klasa ArcVariableState

Obiekt klasy ArcVariableState przechowuje informacje dotyczące pojedynczej wartości archiwalnej zmiennej procesowej. Tablicę wartości archiwalnych, będącą wynikiem zapytania o przebieg archiwalny zmiennej, można otrzymać poprzez właściwość Values interfejsu IArcQueryResult.


3.7.1.1 IsBad

3.8.1.1 IsBad

bool IsBad { get; }

ReadOnly Property IsBad As Boolean

Właściwość określa, czy status wartości zmiennej jest niepoprawny.


3.7.1.2 IsGood

3.8.1.2 IsGood

bool IsGood { get; }

ReadOnly Property IsGood As Boolean

Właściwość określa, czy status wartości zmiennej jest poprawny.


3.7.1.3 IsUncertain

3.8.1.3 IsUncertain

bool IsUncertain { get; }

ReadOnly Property IsUncertain As Boolean

Właściwość określa, czy status wartości zmiennej jest niepewny.


3.7.1.4 Status

3.8.1.4 Status

public StatusOpc Status { get; }

ReadOnly Property Status As Askom.Ascent.StatusOpc

Właściwość zwraca szczegółowy status wartości zmiennej procesowej w konwencji statusu interfejsu komunikacyjnego OPC. Do prostych testów statusu zmiennej zalecane jest korzystanie z właściwości IsGood, IsBad i IsUncertain.


3.7.1.5 TimeStamp

3.8.1.5 TimeStamp

DateTime TimeStamp { get; }

ReadOnly Property TimeStamp As Date

Właściwość zwraca stempel czasu wartości archiwalnej.


3.7.1.6 Value

3.8.1.6 Value

object Value { get; }

ReadOnly Property Value As Object

Właściwość zwraca wartość archiwalną zmiennej procesowej z momentu czasu określonego właściwością TiemStamp.


Interfejs IAlarm

3.9 Interfejs IAlarm

Interfejs IAlarm pozwala na uzyskanie informacji dotyczących definicji alarmu i jego aktualnego stanu. Pozwala też na kontrolę stanu alarmu: zgłaszanie, kończenie i potwierdzanie alarmu.

Referencję do interfejsu IAlarm dla wybranego alarmu można uzyskać poprzez wywołanie funkcji GetAlarm z interfejsu IApplication.


3.8.1.1 AlarmState

3.9.1.1 AlarmState

AlarmState AlarmState { get; }

ReadOnly Property AlarmState As AlarmState

Właściwość zwraca obiekt klasy AlarmState, z którego można odczytać informacje dotyczące aktualnego stanu alarmu kontrolowanego przez posiadaną referencję do interfejsu IAlarm. Jeżeli w logu alarmów aktywnych zarejestrowane jest więcej niż jedno zdarzenie, to zwracany jest stan zdarzenia najmłodszego.


3.8.1.2 Definition

3.9.1.2 Definition

AlarmProperties Definition { get; }

ReadOnly Property Definition As AlarmProperties

Właściwość zwraca obiekt klasy AlarmProperties, z którego można odczytać informacje dotyczące definicji alarmu kontrolowanego przez posiadaną referencję do interfejsu IAlarm.


3.8.1.3 Domain

3.9.1.3 Domain

string Domain { get; }

ReadOnly Property Domain As String

Właściwość zwraca nazwę domeny alarmowej, do której należy alarm kontrolowany przez posiadaną referencję do interfejsu IAlarm.


3.8.1.4 Id

3.9.1.4 Id

string Id { get; }

ReadOnly Property Id As String

Właściwość zwraca identyfikator alarmu kontrolowanego przez posiadaną referencję do interfejsu IAlarm.


3.8.2.1 Accept

3.9.2.1 Accept

bool Accept();

Function Accept() As Boolean

Metoda służy do potwierdzenia alarmu. Jej efekt działania jest identyczny z potwierdzeniem alarmu przez operatora w tabeli alarmów. Funkcja zwraca wstępny status wykonania. Wartość true oznacza, że operacja została przyjęta do realizacji. Potwierdzenie może jednak nie dojść do skutku z powodu niespełnienia warunków sprawdzanych w późniejszych fazach realizacji operacji, np. brak uprawnienia stanowiska do potwierdzania alarmów w domenie.


3.8.2.2 Cancel

3.9.2.2 Cancel

bool Cancel(params object[ ] aParameters);

bool Cancel(DateTime aEndTime, params object[ ] aParameters);

Function Cancel(ByVal ParamArray aParameters( ) As Object) As Boolean

Function Cancel(ByVal aEndTime As Date , ByVal ParamArray aParameters( ) As Object) As Boolean

Metoda pozwala na zgłoszenie końca zdarzenia alarmowego. Opcjonalna tabela parametrów aParameters służy do przekazania dodatkowych danych związanych ze zdarzeniem. Znaczenie tych danych zależy wyłącznie od projektanta aplikacji. Wersja wywołania z parametrem aEndTime pozwala na jawne podanie czasu zdarzenia. W przypadku wywołania bez parametru aEndTime czas zdarzenia jest ustawiany automatycznie na chwilę bieżącą. Metodę można wykonać tylko dla alarmów, które należą do zewnętrznej strategii rozpoznania alarmów.

Funkcja zwraca wstępny status wykonania. Wartość true oznacza, że operacja została przyjęta do realizacji. Zgłoszenie może jednak zostać zignorowane z powodu niespełnienia warunków sprawdzanych w późniejszych fazach realizacji operacji, np. stanowisko nie jest kontrolerem aktywnym domeny i użyto zwykłej strategii zewnętrznej (nie globalnej).


3.8.2.3 Raise

3.9.2.3 Raise

bool Raise(params object[ ] aParameters);

bool Raise(DateTime aStartTime, params object[ ] aParameters);

Function Raise(ByVal ParamArray aParameters( ) As Object) As Boolean

Function Raise(ByVal aStartTime As Date , ByVal ParamArray aParameters( ) As Object) As Boolean

Metoda pozwala na zgłoszenie początku zdarzenia alarmowego. Opcjonalna tabela parametrów aParameters służy do przekazania dodatkowych danych związanych ze zdarzeniem. Znaczenie tych danych zależy wyłącznie od projektanta aplikacji. Wersja wywołania z parametrem aStartTime pozwala na jawne podanie czasu zdarzenia. W przypadku wywołania bez parametru aStartTime czas zdarzenia jest ustawiany automatycznie na chwilę bieżącą. Metodę można wykonać tylko dla alarmów, które należą do zewnętrznej strategii rozpoznania alarmów.

Funkcja zwraca wstępny status wykonania. Wartość true oznacza, że operacja została przyjęta do realizacji. Zgłoszenie może jednak zostać zignorowane z powodu niespełnienia warunków sprawdzanych w późniejszych fazach realizacji operacji, np. stanowisko nie jest kontrolerem aktywnym domeny i użyto zwykłej strategii zewnętrznej (nie globalnej).


3.8.2.4 RegisterStateEvent

3.9.2.4 RegisterStateEvent

void RegisterStateEvent(AlarmEvent aFunction);

Sub RegisterStateEvent(ByVal aFunction As AlarmEvent)

Funkcja służy do zarejestrowania funkcji zwrotnej, która będzie wywoływana przy każdej zmianie stanu kontrolowanego alarmu. Dotyczy to zarówno zdarzeń początku i końca alarmu, jak i zmian stanu spowodowanych działaniami operatora, np. potwierdzenie alarmu.

Parametr aFunction określa funkcję monitorującą stan alarmu – musi ona być zgodna z delegatem AlarmEvent.

delegate void AlarmEvent(string aDomain, string aAlarm, AlarmState aAlarmState, AlarmEventType aEventType);

Delegate Sub AlarmEvent(ByVal aDomain As String, ByVal aAlarm As String, ByVal aAlarmState As AlarmState ,ByVal aEventType As AlarmEventType)

W momencie wywołania funkcji monitorującej przekazywane są do niej cztery parametry. Parametry aDomain i aAlarm określają odpowiednio nazwę domeny i identyfikator alarmu, którego wywołanie funkcji zwrotnej dotyczy. Parametr aAlarmState przekazuje obiekt, z którego można odczytać aktualny stan alarmu. Parametr aEventType określa rodzaj zdarzenia. Typ wyliczeniowy AlarmEventType przybiera następujące wartości: AlarmBegin (wykrycie początku alarmu) , AlarmEnd (wykrycie końca alarmu), AlarmManagement (zmiana stanu wynikająca z działań operatora, np. potwierdzenia alarmu), DomainStart (uruchomienie pracy domeny), DomainStop (zatrzymanie pracy domeny).

Funkcję monitorującą można wyrejestrować przy pomocy metody UnregisterStateEvent.

Przykład:

C#

       IApplication application;

       void AlarmFun(string aDomain, string aAlarm, AlarmState aAlarmState,

                     AlarmEventType aEventType)

       {

// kod funkcji zwrotnej

          if (aEventType == AlarmEventType.AlarmBegin)

             application.ReportMessage(EvoMessageType.Info, aAlarm + ": alarm rozpoczęty");

       }

       public bool Initialize(string[] aParameters, IApplication aApplication)

       {

          application = aApplication;

          IAlarm ia = application.GetAlarm("Blok1","DemoB1");

          ia.RegisterStateEvent(AlarmFun);

          return false;

       }

VB

Dim application As IApplication

Sub AlarmFun(aDomain As String, aName As String, aAlarmState As AlarmState, aEventType As AlarmEventType)

'  kod funkcji zwrotnej

   If aEventType = AlarmEventType.AlarmBegin Then

       application.ReportMessage(EvoMessageType.Info, aName & ": alarm rozpoczęty")

   End If

End Sub

Public Function Initialize(ByVal aParameters() As String, ByVal aApplication As _

IApplication) As Boolean Implements IScript.Initialize

   application = aApplication

   Dim ia As IAlarm

   ia = application.GetAlarm("Blok1", "DemoB1")

   ia.RegisterStateEvent(AddressOf AlarmFun)

   Return False

End Function

Powyższy kod tworzy obiekt IAlarm dla alarmu DemoB1 z domeny Blok1. Następnie rejestrowana jest funkcja monitorująca AlarmFun, która przy każdej zmianie stanu alarmu sprawdza rodzaj zdarzenia i zapisuje w logu komunikatów informację o zdarzeniach początku alarmu.


3.8.2.5 UnregisterStateEvent

3.9.2.5 UnregisterStateEvent

void UnregisterStateEvent();

Sub UnregisterStateEvent()

Wyrejestrowanie funkcji monitorującej zmiany stanu alarmu, która została wcześniej zarejestrowana przy pomocy funkcji RegisterStateEvent.


Klasa AlarmState

3.10 Klasa AlarmState

Obiekt AlarmState przechowuje informacje dotyczące aktualnego stanu alarmu. Obiekty AlarmState można uzyskać za pośrednictwem właściwości AlarmState interfejsu IAlarm. Dostarczane są także jako parametr funkcji monitorującej zmiany stanu alarmów, rejestrowanej funkcją RegisterStateEvent interfejsu IAlarm.

Dostęp do stanu alarmów realizowany jest na bazie logu alarmów aktywnych – oznacza to, że szczegółowe dane dotyczące stanu alarmu są dostępne tylko wtedy, gdy zdarzenie dotyczące tego alarmu znajduje się w logu alarmów aktywnych. Gdy dane nie są dostępne, właściwość IsActive obiektu jest równa false.


3.9.1.1 AcceptanceOperatorId

3.10.1.1 AcceptanceOperatorId

string AcceptanceOperatorId { get; }

ReadOnly Property AcceptanceOperatorId As String

Właściwość zwraca identyfikator użytkownika, który potwierdził zdarzenie alarmowe.


3.9.1.2 AcceptanceStationName

3.10.1.2 AcceptanceStationName

string AcceptanceStationName { get; }

ReadOnly Property AcceptanceStationName As String

Właściwość zwraca nazwę stanowiska, na którym zostało potwierdzone zdarzenie alarmowe.


3.9.1.3 AcceptanceTimeStamp

3.10.1.3 AcceptanceTimeStamp

DateTime AcceptanceTimeStamp { get; }

ReadOnly Property AcceptanceTimeStamp As Date

Właściwość zwraca czas potwierdzenia zdarzenia alarmowego przez użytkownika.


3.9.1.4 BeginDetectionTimeStamp

3.10.1.4 BeginDetectionTimeStamp

DateTime BeginDetectionTimeStamp { get; }

ReadOnly Property BeginDetectionTimeStamp As Date

Właściwość zwraca czas wykrycia początku zdarzenia alarmowego.


3.9.1.5 BeginExprValue

3.10.1.5 BeginExprValue

object BeginExprValue { get; }

ReadOnly Property BeginExprValue As Object

Właściwość zwraca wartość wyrażenia powiązanego z alarmem, wyliczoną w momencie wykrycia początku alarmu.


3.9.1.6 BeginTimeStamp

3.10.1.6 BeginTimeStamp

DateTime BeginTimeStamp { get; }

ReadOnly Property BeginTimeStamp As Date

Właściwość zwraca czas początku zdarzenia alarmowego.


3.9.1.7 EndDetectionTimeStamp

3.10.1.7 EndDetectionTimeStamp

DateTime EndDetectionTimeStamp { get; }

ReadOnly Property EndDetectionTimeStamp As Date

Właściwość zwraca czas wykrycia końca zdarzenia alarmowego.


3.9.1.8 EndExprValue

3.10.1.8 EndExprValue

object EndExprValue { get; }

ReadOnly Property EndExprValue As Object

Właściwość zwraca wartość wyrażenia powiązanego z alarmem, wyliczoną w momencie wykrycia końca alarmu.


3.9.1.9 EndTimeStamp

3.10.1.9 EndTimeStamp

DateTime EndTimeStamp { get; }

ReadOnly Property EndTimeStamp As Date

Właściwość zwraca czas końca zdarzenia alarmowego.


3.9.1.10 FormattedBeginText

3.10.1.10 FormattedBeginText

string FormattedBeginText { get; }

ReadOnly Property FormattedBeginText As String

Właściwość zwraca tekst opisujący początek zdarzenia alarmowego. W zwróconym tekście wygenerowane są wszystkie dynamicznie tworzone wstawki związane z parametrami zgłoszenia.


3.9.1.11 FormattedEndText

3.10.1.11 FormattedEndText

string FormattedEndText { get; }

ReadOnly Property FormattedEndText As String

Właściwość zwraca tekst opisujący koniec zdarzenia alarmowego. W zwróconym tekście wygenerowane są wszystkie dynamicznie tworzone wstawki związane z parametrami zgłoszenia.


3.9.1.12 IsAccepted

3.10.1.12 IsAccepted

bool IsAccepted { get; }

ReadOnly Property IsAccepted As Boolean

Właściwość określa, czy zdarzenie alarmowe zostało potwierdzone przez użytkownika.


3.9.1.13 IsActive

3.10.1.13 IsActive

bool IsActive { get; }

ReadOnly Property IsActive As Boolean

Właściwość określa, czy zdarzenie dotyczące kontrolowanego przez obiekt alarmu znajduje się w logu alarmów aktywnych. Wartość false oznacza, że brak jest informacji o alarmie i wszystkie pozostałe właściwości obiektu AlarmState mają nieokreśloną wartość.


3.9.1.14 IsExcluded

3.10.1.14 IsExcluded

bool IsExcluded { get; }

ReadOnly Property IsExcluded As Boolean

Właściwość określa, czy alarm jest wykluczony z obsługi. Alarmy wykluczone nie są pokazywane na tabelach alarmów, ale dane o nich są przechowywane w logu alarmów aktywnych i są dostępne dla skryptów.


3.9.1.15 IsFinished

3.10.1.15 IsFinished

bool IsFinished { get; }

ReadOnly Property IsFinished As Boolean

Właściwość określa, czy alarm przechowywany w logu alarmów aktywnych został już zakończony. W zależności od konfiguracji, log alarmów aktywnych może przez pewien czas pamiętać dane dotyczące zdarzenia już zakończonego. Alarm należy traktować jako aktywny (niezakończony) wtedy, gdy właściwość IsActive jest równa true i właściwość IsFinished jest równa false.


3.9.1.16 WasFiltered

3.10.1.16 WasFiltered

bool WasFiltered { get; }

ReadOnly Property WasFiltered As Boolean

Właściwość określa, czy zdarzenie alarmowe zarejestrowane w logu podlegało mechanizmowi filtrów czasowych.


Klasa AlarmProperties

3.11 Klasa AlarmProperties

Obiekt AlarmProperties przechowuje informacje dotyczące definicji alarmu. Obiekt można uzyskać za pośrednictwem właściwości Definition interfejsu IAlarm.


3.10.1.1 Action

3.11.1.1 Action

string Action { get; }

ReadOnly Property Action As String

Właściwość zwraca treść akcji operatorskiej zdefiniowanej dla alarmu.


3.10.1.2 DetectionParameters

3.11.1.2 DetectionParameters

string DetectionParameters { get; }

ReadOnly Property DetectionParameters As String

Właściwość zwraca atrybut Parametry wykrywania definicji alarmu. W przypadku realizacji zewnętrznej strategii wykrywania alarmów przy pomocy mechanizmu skryptów, można wykorzystać właściwość DetectionParameters jako źródło informacji precyzującej sposób rozpoznawania stanu alarmu.


3.10.1.3 BeginText

3.11.1.3 BeginText

string BeginText { get; }

ReadOnly Property BeginText As String

Właściwość zwraca tekst początku alarmu w oryginalnej formie użytej w definicji alarmu – wstawki formatujące {} nie są przekształcone.


3.10.1.4 EndText

3.11.1.4 EndText

string EndText { get; }

ReadOnly Property EndText As String

Właściwość zwraca tekst końca alarmu w oryginalnej formie użytej w definicji alarmu – wstawki formatujące {} nie są przekształcone.


3.10.1.5 Id

3.11.1.5 Id

string Id { get; }

ReadOnly Property Id As String

Właściwość zwraca identyfikator alarmu, którego atrybuty są przechowywane w obiekcie.


3.10.1.6 IsStartOnly

3.11.1.6 IsStartOnly

bool IsStartOnly { get; }

ReadOnly Property IsStartOnly As Boolean

Właściwość zwraca informację, czy alarm należy do kategorii powiadomienie. Alarmy tej kategorii nie posiadają zdarzeń końca.


3.10.1.7 Priority

3.11.1.7 Priority

int Priority { get; }

ReadOnly Property Priority As Integer

Właściwość zwraca priorytet (ważność) alarmu. Możliwe są poniższe wartości:

  • 0 – alarm krytyczny

  • 1 – alarm ważny

  • 2 – alarm zwykły

  • 3 – ostrzeżenie

  • 4 – komunikat


3.10.1.8 Strategy

3.11.1.8 Strategy

string Strategy { get; }

ReadOnly Property Strategy As String

Właściwość zwraca nazwę strategii wykrywania alarmu.


Klasa TrendPatternPoint

3.12 Klasa TrendPatternPoint

Obiekt TrendPatternPoint definiuje pojedynczy punkt krzywej wzorcowej. Tablicę punktów krzywej wzorcowej można pobrać przy pomocy metody GetTrendPatternPoints interfejsu IApplication.


3.11.1.1 TimeStamp

3.12.1.1 TimeStamp

TimeSpan TimeStamp { get; }

ReadOnly Property TimeStamp As System.TimeSpan

Właściwość określa czas punktu krzywej wzorcowej – podawany jako odstęp czasu od początku krzywej.


3.11.1.2 Value

3.12.1.2 Value

double Value { get; }

ReadOnly Property Value As Double

Właściwość określa wartość punktu krzywej wzorcowej.


Klasa AsalertAccess

3.13 Klasa AsalertAccess

Obiekt klasy AsalertAccess pozwala na wysłanie alertu(powiadomienia) za pośrednictwem serwera programu AsAlert. Dostęp do obiektu AsalertAccess uzyskuje się za pośrednictwem właściwości Asalert interfejsu IApplication.


3.13.1.1 Send

bool Send(string aTo, string aFrom, string aSubject, string aMessage);

Function Send (ByVal aTo As String, ByVal aFrom As String, ByVal Subject As String, ByVal aMessage As String) As Boolean

Metoda Send pozwala na wysłanie alertu za pośrednictwem programu AsAlert.

Parametr aTo określa nazwę adresata, do którego alert ma zostać wysłany. Adresat ten musi zostać wcześniej zdefiniowany w programie AsAlert.

Parametry aFrom, aSubject i aMessage określają treść alertu, kolejno: nazwę nadawcy, temat alertu i jego treść.

Metoda zwraca status poprawności wykonania operacji.

Przed wykonaniem metody Send należy użyć metodę SetAccessData w celu określenia parametrów komunikacji z programem AsAlert (o ile są różne od domyślnych).


SetAccessData

3.13.1.2 SetAccessData

void SetAccessData(string aMachineName, string aUserName, string aPassword);

Sub SetAccessData(ByVal aMachineName As String, ByVal aUserName As String, ByVal aPassword As String)

Metoda służy do określenia parametrów komunikacyjnych z serwerem programu AsAlert. Parametr aMachineName określa systemową nazwę komputera, na którym program AsAlert został zainstalowany. Domyślna, pusta wartość oznacza komunikację z serwerem lokalnym, znajdującym się na tym samym komputerze co aplikacja.

Parametr aUserName pozwala na określenie nazwy użytkownika zdefiniowanego w programie AsAlert, który zostanie użyty w operacji wysłania alertu. Domyślna nazwa użytkownika to AsixEvo. Parametr aPassword służy do podania hasła użytkownika (domyślnie – brak hasła). W celu poprawnego działania, należy utworzyć odpowiednika użytkownika w programie AsAlert.


RestartIfFailed

3.3.1.1 AllowMultipleInstances

MultipleInstanceMode AllowMultipleInstances
 { get;
 set;
 }

Property AllowMultipleInstances As MultipleInstancesMode

Właściwość określa sposób kontrolownia prób wielokrotnego (w tym samym czasie) uruchomienia tego samego skryptu. Tryb wyliczeniowy MultipleInstancesMode może przybierać poniższe wartości:

Always – Można bez ograniczeń uruchamiać skrypt wielokrotnie.

Never – W danym momencie może pracować tylko jedna instancja skryptu

IfDifferentParamters – Można wielokrotnie uruchomić skrypt pod warunkiem użycia różnych parametrów uruchomienia (wartość domyślna).


Rodzaje agregatów danych archiwalnych

W każdym przypadku, w którym w aplikacji wymagany jest dostęp do zagregowanych danych historycznych konieczne jest podanie nazwy agregatu. Dotyczy to obiektu Wykres, funkcji HorizonAggregate i RangeAggregate, interfejsów modelu skryptowego.

Nazwa | Znaczenie
none | brak agregacji
start | Wartość na początku interwału.
end | Wartość na końcu interwału.
delta | Różnica wartości na końcu i na początku interwału.
min | Minimalna wartość w interwale.
max | Maksymalna wartość w interwale.
range | Różnica między maksymalna a minimalna wartością w interwale.
total | Suma wartości ważonych czasowo w interwale (całka po czasie).
average | Średnia wartości ważonych czasowo w interwale.
average0 | Średnia wartości ważonych czasowo w interwale. W okresach, w których wartość jest niedostępna do obliczeń, używana jest wartość 0.
sumup | Suma wartości dodatnich zmian, od ostatniej znanej wartości przed rozpoczęciem, do ostatniej wartości przed końcem przedziału próbkowania.
sumdown | Suma wartości bezwzględnych ujemnych zmian, od ostatniej znanej wartości przed rozpoczęciem, do ostatniej wartości przed końcem przedziału próbkowania.
prevknown | Ostatnio znana (dobra lub niepewna) wartość przed rozpoczęciem przedziału próbkowania. Podaje ostatnią wartość, nawet jeżeli wystąpiła ona bardzo dawno.
last | Ostatnio znana (dobra lub niepewna) wartość w przedziale próbkowania wyłączając koniec przedziału - dla odróżnienia od agregatu end, który zawiera koniec przedziału.
stdev | Ważone czasowo odchylenie standardowe w przedziale próbkowania.
rms | Ważona czasowo średnia kwadratowa w przedziale próbkowania.
avglk | Średnia ważona czasowo w przedziale próbkowania. W miejsce złych lub brakujących wartości wstawia ostatnią znaną wartość.
totallk | Całka w przedziale próbkowania, przy czasie liczonym w sekundach. W miejsce złych lub brakujących wartości wstawia ostatnią znaną wartość.

Szczegółowy opis agregatów oraz ich parametryzacji znajduje się w dokumentacji modułu archiwizacji Aspad (patrz: podręcznik Asix.PDF/CHM).