| |||
| |||
User docs - jak napisać aplikację SCADA używając scada-tgz Windows.FormsNa początku załączamy następujące biblioteki: using System; using System.Drawing; using System.Windows.Forms; using System.Timers; using ScadaForms; Tworzymy klasę w której umieszczamy deklaracje zmiennych oraz funkcję Main: class program1 { static Slider slider1; static Timer timer; static Modbus srv; ... static void Main() { ... } } W funkcji Main tworzymy główne okno aplikacji, określamy jego rozmiar i tytuł. Tworzymy też wszystkie kontrolki, ustawiamy ich parametry początkowe oraz określamy ich położenie względem lewego górnego rogu okna aplikacji. Tworzymy też nowy timer i obiekt typu WebService dla serwera komunikacyjnego (np. Modbus). Ustawiamy częstotliwość timera i uruchamiamy go: Form window=new Form(); window.Width=690; window.Height=230; window.Text="Program 1"; slider1=new Slider(); slider1.Reset(0.1f, 0f); slider1.Location=new Point(10, 20); srv=new Modbus(); timer=new Timer(); timer.Interval=500; timer.Start(); Następnie podłączamy funkcje obsługi do zdarzeń: window.Closed+=new EventHandler(onQuit); slider1.ValueChanged+=new EventHandler(onSlider1); timer.Elapsed+=new ElapsedEventHandler(onTimer); Na końcu umieszczamy kontrolki na oknie aplikacji, pokazujemy je i uruchamiamy aplikację: window.Controls.Add(suwak1); window.Show(); Application.Run(); Application.Run spowoduje przejście aplikacji w stan bezczynności z oczekiwaniem na zdarzenia. Oznacza to że dalsze działanie aplikacji ogranicza się wyłącznie do obsługiwania zdarzeń. Zakończenie aplikacji jest możliwe poprzez wywołanie funkcji Application.Exit. Wywołanie to powinno nastąpić w funkcji obsługi zdarzenia zamknięcia okna głównego aplikacji. W przeciwnym wypadku zamknięcie okna nie spowoduje zakończenia aplikacji: static void onQuit(object o, EventArgs e) { Application.Exit(); } Głównym procesem aplikacji będzie teraz funkcja obsługi timera. Funkcja ta zapewni stałą komunikację poprzez serwer komunikacyjny: static void onTimer(object o, ElapsedEventArgs e) { ... } Dodatkowe zadania mogą też być realizowane w funkcjach obsługi zdarzenia zmiany wartości kontrolki ValueChanged, np. bezpośrednie przesłanie nastawy do sterownika z pominięciem głównego procesu pracującego na timerze: static void onSuwak1(object o, EventArgs e) { ... } GTK#Na początku załączamy następujące biblioteki: using Gtk; using System; using System.Timers; using ScadaGtk; Następnie tak jak w aplikacji Windows.Forms tworzymy klasę w której umieszczamy deklaracje zmiennych oraz funkcję Main. Utworzenie kontrolek, timerów i serwera komunikacyjnego przebiega identycznie. Inaczej wygląda natomiast tworzenie okna głównego aplikacji. Na samym początku funkcji Main musimy wywołać funkcję Application.Init. Funkcja ta zainicjuje bibliotekę GTK#. W aplikacjach GTK# inny jest sposób rozmieszczania kontrolek na oknie głównym. Okno aplikacji GTK# potrafi pomieścić tylko jedną kontrolkę. Do umieszczania większej ilości kontrolek służą specjalne kontrolki, pudełka pionowe i poziome. Pudełko jest pustą kontrolką na której można umieszczać inne kontrolki obok siebie, pionowo lub poziomo. Umieszczanie kontrolek w pudełku nazywa się pakowaniem. Aby umieścić trzy kontrolki obok siebie, a pod nimi następne cztery, należy pierwsze trzy kontrolki zapakować do poziomego pudełka, następne cztery do drugiego poziomego pudełka, poziome pudełka zapakować do pionowego pudełka a pionowe pudełko umieścić na oknie głównym aplikacji. Dzięki takiemu podejściu nie musimy już określać ani rozmiaru okna głównego ani dokładnego położenia kontrolek, ponieważ pudełka automatycznie dostosowują swój rozmiar do rozmiarów kontrolek a okno do rozmiarów pudełek: Application.Init(); window=new Gtk.Window("Program 2"); window.Resizable=false; VBox box0=new VBox(false, 10); box0.BorderWidth=10; slider1=new Slider(); slider1.Reset(0.1f, 0f); ... srv=new Modbus(); timer=new Timer(); timer.Interval=500; timer.Start(); ... window.DeleteEvent+=new DeleteEventHandler(onQuit); slider1.ValueChanged+=new EventHandler(onSlider1); timer.Elapsed+=new ElapsedEventHandler(onTimer); ... box0.PackStart(slider1, true, false, 0); window.Add(box0); window.ShowAll(); Application.Run(); ASP.NETNajpierw tworzymy stronę aspx aplikacji. Na początku definiujemy klasę zawierającą kod aplikacji oraz definiujemy znacznik dla kontrolek ScadaWeb: <%@ Page Language="C#" Inherits="program3" %> <%@ Register TagPrefix="Scada" Namespace="ScadaWeb" assembly="ScadaWeb" %> Na stronie umieszczamy formularz ze zdefiniowanym atrybutem id. Wewnątrz formularza umieszczamy wszystkie kontrolki ASP.NET oraz ScadaWeb. W atrybucie id znaczników kontrolek definiujemy nazwy zmiennych: <form id="form1" runat="server"> ... <ASP:TextBox id="user" runat="server" /> ... <Scada:Slider id="slider1" runat="server" /> ... <form> Następnie tworzymy aplikację. Załączamy następujące biblioteki: using System; using System.Web.UI; using System.Web.UI.WebControls; using ScadaWeb; Tworzymy publiczną klasę pochodną od klasy Page. Klasa ta nie zawiera funkcji Main, zamiast niej stosujemy dwie inne funkcje, OnInit i Page_Load: public class app3 : Page { protected Slider slider1; ... override protected void OnInit(EventArgs e) { slider1.ValueChanged+=new EventHandler(onSlider1); ... base.OnInit(e); } protected void Page_Load(object o, EventArgs e) { if (!Page.IsPostBack) { slider1.Reset(0.1f, 0f); ... } else { ... } } } W funkcji OnInit należy przypisać funkcje obsługi do zdarzeń kontrolek. Funkcja Page_Load jest wywoływana przy każdym odwołaniu do strony, sprawdzając parametr Page.IsPostBack możemy wyróżnić pierwsze odwołanie, czyli uruchomienie aplikacji, aby przypisać początkowe wartości kontrolkom. W aplikacjach ASP.NET używanie timerów ma zupełnie inny sens, ponieważ działanie aplikacji oparte jest na przesyłaniu danych pomiędzy serwerem a przeglądarką. Timer pracuje tylko po stronie serwera a serwer nie może przesłać do przeglądarki żadnych danych bez uprzedniego zażądania ich przez przeglądarkę. W aplikacjach ASP.NET nie powinno się również stosować automatycznego odświeżania stron WWW ponieważ podczas automatycznego odświeżania nie jest wysyłany formularz, zostanie ono więc potraktowane jako uruchomienie aplikacji od nowa. Jedynym sposobem na automatyczne wysłanie formularza jest skrypt JavaScript. Biblioteka ScadaWeb zawiera dodatkową kontrolkę, AutoPostBack, generującą ten kod. Należy umieścić ją w formularzu na tronie aspx: <Scada:AutoPost id="autopost" runat="server" /> Oraz zainicjować ją podając czas w milisekundach po jakim nastąpi automatyczne odesłanie formularza oraz nazwę formularza do przesłania: autopost.Reset(10000, "form1"); Serwery komunikacyjneAby aplikacja mogła korzystać z serwera musi ona znać adres oraz funkcje dostępne w WebService. Do aplikacji należy załączyć bibliotekę zawierającą deklaracje publicznych funkcji serwera, tzw. client proxy. Kod tej biblioteki można wygenerować automatycznie znając adres WebService: wsdl http://address:port/server.asmx Następnie w kodzie aplikacji należy zdefiniować obiekt typu WebService zadeklarowany w bibliotece client proxy, dodać do niego obiekt CookieContainer w którym serwer będzie przechowywał swoje zmienne i już można wywoływać funkcje serwera: static Modbus srv; srv=new Modbus(); srv.CookieContainer=new System.Net.CookieContainer(); try { res=srv.RSConfig(19200, 1, 2, 8, 1); } catch { ... } Wywołanie funkcji serwera który nie jest dostępny (np. w wyniku zerwania połączenia) spowoduje wystąpienie wyjątku który musi być obsłużony. Dlatego każde wywołanie funkcji WebService musi być umieszczone wewnątrz instrukcji try/catch. W przypadku zmiany adresu WebService nie trzeba rekompilować biblioteki client proxy, wystarczy zmodyfikować parametr Url obiektu WebService podając nowy adres: srv.Url="http://address:port/server.asmx"; | |||
|