Previous Contents Next

Rozdział 3   Projekt i implementacja systemu

3.1   Ogólna struktura systemu

Przedstawione w poprzednim rozdziale wymagania wobec systemu determinują już częściowo jego architekturę. Jedną z najważniejszych decyzji implementacyjnych, jakie należało podjąć, był wybór sposobu prezentacji danych po stronie klienta. Było tu co najmniej kilka możliwości.

Po pierwsze, można było stworzyć rozwiązanie dedykowane dla mojego systemu. Pozwoliłoby to na najlepsze dopasowanie cech programów klienckich do wymagań systemu. Z drugiej strony rozwiązanie to ma sporo wad. Oprogramowanie klienckie należałoby napisać od nowa i to w języku oferującym niezależność od systemu operacyjnego (bo tego wymagamy od klienta). Praktycznie wchodzi tu w grę tylko Java, nie zapewniająca najlepszej wydajności. Poza tym trzeba by i tak generować oddzielny rodzaj danych do wyświetlania w przeglądarce WWW. Wynika to z zadeklarowanej w wymaganiach możliwości takiego dostępu do systemu. Mogłby on co prawda oferować mniejszą funkcjonalność (np. konieczność ręcznego odświeżania wartości parametrów).

Innym możliwym podejściem jest zastosowanie przeglądarki WWW jako podstawowego oprogramowania klienckiego. Rozwiązuje to problemy niezależności od systemu operacyjnego, nie trzeba pisać i instalować oprogramowania klienckiego. Takie rozwiązanie jest bardziej eleganckie i zgodne z panującą obecnie tendencją do tworzenia aplikacji wykorzystujących interfejs WWW. Umożliwia także czerpanie korzyści z rozwoju technologii internetowych, nie zamyka systemu skazując go na użycie specjalizowanych rozwiązań.

Jednak stosowany w przeglądarkach język HTML niezbyt nadaje się do prezentacji dynamicznej, interaktywnej grafiki. Umożliwia tylko wykorzystywanie grafiki bitmapowej, wymagającej pobierania z serwera dużej ilości danych. Tymczasem tworzone schematy mają charakter wektorowy i lepiej by było, aby właśnie tak były prezentowane. Pozwala to również na skalowanie i drukowanie bez utraty jakości.

Kłopotliwe byłoby także odświeżanie wartości parametrów. Niedopuszczalne jest ściąganie całego, być może dużego obrazka w sytuacji, gdy zmienił się w nim jeden napis. Nawet w szybkiej sieci lokalnej nie dałoby się uniknąć widocznego odświeżania okna przeglądarki. Wykorzystanie apletów Javy do prezentowania dynamicznej części schematu oznaczałoby tak naprawdę tworzenie rozwiązania dedykowanego, tyle że uruchamianego w przeglądarce WWW wyposażonej w maszynę wirtualną Javy. Poza tym Java w przeglądarkach nie oferuje wystarczającej stabilności.

Można sobie wyobrazić, że elementy statyczne prezentowane są jako bitmapa w tle, a na niej znajdują się wartości parametrów w postaci tekstowej. Dużo ciekawsze efekty można jednak osiągnąć dopuszczając wpływ parametrów na prezentowaną grafikę (np. termometr ze słupkiem rtęci pokazującym temperaturę). Podobnie chcielibyśmy mieć możliwość umieszczania na schemacie animacji i obszarów aktywnych (dowiązań). Tu także można wyobrazić sobie generowanie animacji w postaci animowanych obrazków w formacie GIF i użycie elementów <map/> HTML. Jednak generowanie takiej strony byłoby rzeczą trudną i niektóre efekty byłyby trudne lub niemożliwe do osiągnięcia.

Najlepiej więc byłoby zmusić przeglądarkę do wyświetlania bezpośrednio interaktywnej, dynamicznej grafiki wektorowej. Jednym ze sposobów jest wykorzystanie wtyczek do wyświetlania stron wykonanych w technologii Flash firmy Macromedia. Są one dostępne dla wszystkich powszechnie używanych przeglądarek. Technologia ta jest dość popularna właśnie między innymi ze względu na osiągane bardzo dobre efekty wizualne, a także możliwość tworzenia stron dynamicznych i interaktywnych. Z mojego punktu widzenia ma jednak także sporo wad. Jest to format binarny, komercyjny produkt jednej firmy, dość popularny, nie będący jednak standardem, jak np. HTML. O ile wtyczki są bezpłatne, o tyle narzędzia do tworzenia stron kosztują sporo. Nie ma także oczywiście żadnych narzędzi darmowych, rozpowszechniantch na licencji pozwalającej na modyfikację kodu źródłowego, w tym na przykład do generowania zawartości w technologii Flash po stronie serwera HTTP.

Na zapotrzebowanie na prawdziwą grafikę wektorową dla potrzeb WWW odpowiedziała w końcu instytucja najbardziej do tego uprawniona -- World Wide Web Consortium (dalej będę się posługiwał skrótem W3C). Pod koniec lat 90-tych rozpoczęła pracę nad standardem SVG -- Scalable Vector Graphics. We wrześniu 2001 roku SVG osiągnęła status rekomendacji, czyli oficjalnego starnardu W3C. Standard definiuje oparty na XML język opisu grafiki wektorowej przeznaczonej do stosowania w sieci Web. Więcej informacji o SVG znajduje się w p. 3.2. Mimo nienajlepszego poziomu rozwoju implemetacji SVG, możliwość wykorzystania otwartego standardu oraz fakt, że docelowe zastosowanie SVG odpowiada dokładnie moim potrzebom, zdecydowało o wyborze tego rozwiązania.

Dodatkowym atutem jest oparcie SVG na XML, co pozwala na proste i naturalne rozszerzanie SVG o dodatkowe elementy, mieszanie z innymi typami danych (a więc osadzanie w innych dokumentach XML), a także zapewnia otwartość rozwiązania na przyszłe modyfikacje i ulepszenia.

Ponieważ, jak już pisałem, SVG nie ma jeszcze odpowiedniego wsparcia w istniejących implementacjach, konieczne okazało się także zapewnienie możliwości generowania zastępczej zawartości dla tych użytkowników, którzy nie mogą lub nie chcą korzystać z przeglądarek specjalizowanych do SVG lub odpowiednich wtyczek. Ponieważ ten sposób prezentacji danych jest drugorzędny i stosowany raczej przez osoby incydentalnie korzystające z systemu, uznałem za dopuszczalne generowanie statycznej grafiki bitmapowej, z dodatkowymi informacjami o dowiązaniach.

Mając wybrany format prezentacji danych, należało się zastanowić nad formatem, w jakim tworzone i przechowywane będą schematy po stronie serwera. Jednym z możliwych rozwiązań jest stworzenie specjalizowanego języka wysokiego poziomu opartego na XML, operującego takimi pojęciami jak rura, zawór, miernik przepływu, pompa, obrotomierz itp. Schematy zapisane w tym języku mogłyby być przekształcane na SVG automatycznie, np. za pomocą procesora XSLT (XML Stylesheet Language Transformations -- więcej o tym języku w p. 3.2). Rozwiązanie takie pozwalałoby się poruszać na dość wysokim poziomie abstrakcji. Stracilibyśmy jednak możliwość dowolnego kształtowania postaci graficznej schematu. Dodanie nowego typu elementu oznaczałoby konieczność definiowania nowego elementu języka. Poza tym należałoby wtedy stworzyć dedykowane narzędzia do tworzenia schematów, co byłoby dość pracochłonne.

Zdecydowałem się więc na wykorzystanie bezpośrednio języka SVG, wzbogaconego o rozszerzenia, które nazwałem Industry Schema Language (ISL). Rozszerzenia te zrealizowane są w postaci przestrzeni nazw XML (ang. XML namespace). Pozwalają one na wstawienie wartości parametru jako zawartości elementu XML lub wartości atrybutu elementu.

Wykorzystanie istniejącego języka rozwiązuje problem narzędzi do tworzenia schematów i eksportu do (importu z) innych formatów danych. Spośród kilku dostępnych darmowych edytorów SVG wybrałem program Sodipodi, który lekko zmodyfikowałem do moich potrzeb. Więcej informacji o Sodipodi znajduje się w p. 3.6. W razie potrzeby schematy można tworzyć także za pomocą profesjonalnych programów do grafiki wektorowej, takich jak Corel Draw czy Adobe Illustrator, których najnowsze wersje pozwalają na import i eksport dokumentów w formacie SVG.

Kolejnym ważnym problemem do rozwiązania, była sprawa dostępu do parametrów. Należało zaprojektować mechanizm, który byłby z jednej strony na tyle ogólny, aby można go było połączyć z dowolnym systemem typu SCADA, jak i na tyle dobrze dopasowany do systemu SZARP, aby możliwa była jego implementacja bez zmian w tym systemie.

Dodatkową trudność sprawia fakt, że mechanizm powinien być niezależny od systemu operacyjnego, na którym działa system bazowy. System SZARP działa pod kontrolą systemu operacyjnego GNU/Linux. Tymczasem większość innych systemów SCADA wykorzystuje systemy Windows (głównie wersje profesjonalne, a więc NT lub 2000). Jedynym sensownym mechanizmem komunikacji międzyprocesowej niezależnym od systemu operacyjnego (tzn. dostępnym w praktycznie każdym systemie i funkcjonującym w środowisku heterogenicznym) jest protokół TCP/IP.

W warstwie aplikacji można było zaprojektować własny protokół lub wykorzystać np. różnego rodzaju mechanizmy RPC (ang. Remote Procedure Call -- zdalne wywoływanie procedur). Jednak rozwiązaniem prostszym, elastyczniejszym i dobrze przystosowanym do przesyłania dużej ilości danych (a mamy przecież do czynienia z grafiką) wydaje się protokół HTTP. Poza tym jest on powszechnie używanym standardem, możemy korzystać z istniejących bibliotek i narzędzi, co nie pozostaje bez wpływu na ilość pracy do wykonania podczas implementacji.

Zdecydowałem się więc na implementację prostego serwera HTTP, udostępniającego informację o parametrach (dalej będę się posługiwał nazwą serwer parametrów). Informacja ta generowana jest standardowo w postaci dokumentów XML. Jest to oczywiście pewna rozrzutność, gdyż XML jest protokołem dość rozrzutnym jeśli chodzi o ilość przesyłanych danych i narzut na przykład przy pobieraniu wartości jednego parametru (a więc zwykle dwa bajty) jest dość duży -- trzeba wygenerować kilkuwierszowy dokument. Jednak przy wymaganej od systemu wydajności nie ma to żadnego znaczenia. Pozwala za to na proste wklejanie uzyskanych w ten sposób danych do schematów.

Serwer parametrów jest jedyną częścią systemu zależną od konkretnego systemu SCADA czy innego źródła danych. Jego zadaniem jest odczytanie konfiguracji bazowego systemu i przekształcanie informacji o wartościach parametrów na dokumenty XML wysyłane klientom. Poza tym ma on za zadanie przekazywanie informacji w drugą stronę, od klienta do systemu bazowego -- w przypadku ustawiania wartości parametrów. Przy zadawaniu parametrów zapewnia on bezpieczeństwo tej operacji przez autoryzację HTTP i tunelowanie połączenia HTTP przez protokół SSL. Więcej informacji o implementacji serwera parametrów znajduje się w p. 3.5. We wcześniejszym p. 3.3 opisuję pokrótce najważniejsze elementy architektury systemu SZARP, istotne z punktu widzenia mojego systemu.




Rysunek 3.1: Ogólna architektura systemu


Każdy prezentowany parametr jest związany z konkretnym udostępniającym go serwerem parametrów. Zwykle serwer parametrów jest związany z jednym źródłem danych (np. serwerem SZARP). Powiązanie takie w wykonanej implementacji wynika między innymi z tego, że komunikacja między serwerem SZARP a serwerem parametrów odbywa się przez pamięć dzieloną, a więc oba programy działają na tej samej maszynie. Możliwość prezentowania jednocześnie danych z różnych serwerów wymusza powiązanie nazwy parametru z udostępniającym go serwerem. Naturalnym rozwiązaniem jest tu wykorzystanie systemu DNS -- nazw serwerów internetowych lub, równorzędnie, adresów IP. Tak więc pełna nazwa parametru składa się z adresu internetowego udostępniającego go serwera parametrów oraz nazwy parametru, unikatowej w obrębie serwera. W związku z unikalnością nazw serwerów w sieci Internet tak otrzymana pełna nazwa parametru jest jednoznaczna globalnie.

Ostatnim brakującym elementem systemu jest mechanizm pozwalający na pobranie wartości parametrów z serwerów parametrów, wstawienie ich do zapisanych w SVG/ISL schematów i wysłanie do zgłaszającego żądanie klienta jako SVG lub, zastępczo, bitmapy. Ponieważ zarówno dane wejściowe, jak i przynajmniej jedna z postaci danych wyjściowych, są dokumentami XML, naturalne staje się wykorzystanie do ich przetwarzania procesora XSLT, połączonego z serwerem HTTP. W ramach pracy wykonałem dwie niezależne implementacje tego elementu systemu. Jedna wykorzystuje kontener serwletów Javy Tomcat i serwer Cocoon. Druga jest moim własnym rozwiązaniem, inspirowanym serwerem Cocoon. Obie pozwalają nie tylko na automatyczne generowanie ze schematów dokumentów SVG i bitmap, ale także innego rodzaju dokumentów, np. HTML. Więcej szczegółów na ten temat zawiera rozdz. 3.7.1. Ten element systemu nazywam roboczo procesorem dokumentów.

Ponieważ ustawianie wartości parametrów wymaga autoryzacji użytkownika i szyfrowania połączeń, jest ono realizowane bezpośrednio na drodze komunikacji klient -- serwer parametrów, z pominięciem procesora XSLT. Jest to spowodowane między innymi przez brak obsługi szyfrowania SSL przez biblioteki klienckie HTTP wykorzystywane przez obie implementacje procesora dokumentów. Poza tym pozwala to uniknąć kłopotów z przekazywaniem informacji o autoryzacji zarówno klienta, jak i serwera przez procesor XSLT. Oczywiście to procesor dokumentów może generować stronę HTML, na której znajduje się formatka do wpisania nowej wartości parametru, jednak kliknięcie przycisku Wyślij powinno inicjować komunikację bezpośrednio z serwerem parametrów.

Ostateczny kształt architektury systemu przestawiono na rys. 3.1. Podsumowując: najniższą warstwę stanowi system SCADA lub inne źródło danych; w mojej konkretnej implementacji jest to system SZARP. Nad nim znajduje się serwer parametrów, o architekturze zależnej od konkretnego źródła danych. Prezentuje on informacje o wartościach parametrów w postaci dokumentu XML, przez protokół HTTP. Informacje te są pobierane przez procesor dokumentów, będący połączeniem procesora XSLT i serwera HTTP. Są one wstawiane do przygotowanych wcześniej przez użytkownika za pomocą edytora SVG + ISL schematów, przekształcane na żądany format wyjściowy (na przykład SVG lub HTML + PNG1) i wysyłane do klienta.

3.2   Wykorzystane technologie

W pracy zastosowałem rozwiązania oparte na meta-języku XML (eXtensible Markup Language). Został on stworzony przez W3C jako uniwersalny język do zapisywania danych różnych typów. W tej chwili ma już bardzo wiele zastosowań. Oparty na nim XHTML jest najnowszą specyfikacją języka stosowanego do tworzenia stron WWW. SOAP jest protokołem typu RPC opartym na XML. XBase pozwala na tworzenie baz danych jako dokumentów XML. Istotnymi specyfikacjami nie będącymi formalnie częścią XML-a, ale powszechnie używanymi w połączeniu z nim i przyczyniającymi się do jego popularności, są specyfikację XML Namespaces (pozwalająca na łączenie w jednym dokumencie XML danych różnych typów), XPath i XPointer (określające sposób adresowania fragmentów dokumentów XML) oraz XLink (służąca do opisywania połączeń między obiektami XML) [15].

Jednym z najczęstszych obecnych zastosowań XML-a jest używanie go do zapisywania treści, które potem będą prezentowane na stronach WWW w postaci dokumentów HTML lub innych. XML umożliwia oddzielenie treści dokumentu (jego zawartości informacyjnej) od sposobu prezentacji. Ułatwia to zarządzanie dużymi serwisami, umożliwia łatwe ich modyfikacje i generowanie z tych samych informacji różnych dokumentów końcowych (np. stron WWW, dokumentów PDF i innych).

Jest to także jednym z zadań XML w moim projekcie, gdzie schematy zapisane jako dokumenty XML mają być prezentowane klientom w różnych postaciach, zależnie od możliwości interfejsu, z którego korzystają.

Kluczowym mechanizmem w tego typu zastosowaniach jest mechanizm przekształcania dokumentów XML na inne dokumenty. Do tego celu służy język XSLT (XSL Transformations) [20]. Został on zaprojektowany jako język pomocniczy wobec języka XSL (XML Stylesheet Language), służącego do specyfikowania formatowania dokumentów XML. Podstawową rolą XSLT jest więc określanie jak dokument XML ma być przekształcany na inny, sformatowany dokument. XSLT może być jednak używany niezależnie od XSL. I choć jego autorzy zastrzegają się, że nie był on tworzony jako język transformacji XML ogólnego przeznaczenia, to ma dość dużą siłę wyrażania i jest powszechnie używany, np. właśnie do generowania stron WWW z dokumentów XML. W moim projekcie okazał się wystarczającym narzędziem do obróbki schematów.

Szablon XSLT składa się z zestawu zasad określających sposób przekształcania elementów XML. Pojedyncza zasada zawiera wzorzec, do którego musi pasować element, aby zostać przez nią przekształcony, oraz z zawartości, określającej sposób przekształcania elementu. Wzorzec jest wyrażeniem XPath [18][19], co umożliwia wybieranie elementów na podstawie ich nazw, wartości atrybutów jak i położenia wobec innych elementów w drzewie (bo dokument XML ma strukturę drzewa). Zawartość określa, jak ma wyglądać przekształcony element. Może ona składać się z części oryginalnego elementu, innych elementów (w tym zawartych w innych dokumentach) oraz różnego rodzaju konstrukcji specyficznych dla XSLT, jak na przykład instrukcji sterujących. Możliwość odwoływania się do innych dokumentów, być może dostępnych przez sieć, była kluczowa dla projektowanego systemu. Umożliwiła zastępowanie odwołań do wartości parametrów przez te wartości, czytane z dokumentów XML udostępnianych przez serwer parametrów. Więcej o szczegółach wykorzystania XSLT znajduje się w p. 3.7.1.

Inną bardzo ważną dla systemu technologią, także należącą do rodziny XML, jest język opisu grafiki wektorowej SVG -- Scalable Vector Graphics. Został on także opracowany przez World Wide Web Consortium i obecnie (od września 2001 roku) ma status rekomendacji, czyli oficjalnego standardu W3C. W pracach nad specyfikacją uczestniczyli przedstawiciele zarówno dużych firm z ogólnie pojętej branży informatycznej (takich jak Microsoft, IBM, Sun, Hewlett-Packard, Apple, Xerox, Nestscape), jak i specjalizujących się w grafice (Corel, Adobe, Kodak). Ciekawostką może być obecność wśród autorów przedstawicieli firmy Macromedia -- SVG wydaje się bezpośrednią konkurencją dla sztandarowego produktu tej firmy, technologii Flash [21].

SVG służy do opisu dwuwymiarowej wektorowej i mieszanej, wektorowo-rastrowej grafiki. Wykorzystuje inne technologie XML-owe, takie jak XLink, XPointer, CSS (Cascading Stylesheets -- arkusze stylów) i DOM2 (Document Object Model)2. Może być łączony z  językiem SMIL (Synchronized Multimedia Integration Language). Został pomyślany jako standard prezentowania grafiki wektorowej w przeglądarkach WWW. Umożliwia tworzenie dokumentów animowanych, bądź przy wykorzystaniu animacji deklaratywnych, bądź za pomocą skryptów modyfikujących strukturę dokumentu (DOM). Dokumenty SVG mogą być w pełni interaktywne, modyfikując swoją zawartość w odpowiedzi na działania użytkownika, także takie jak zmiana powiększenia dokumentu. Każdy obiekt może być dowiązaniem. Bez problemu można łączyć w jednym dokumencie SVG, XHTML, MathML i ewentualne inne XML-owe języki prezentacji danych. Standard przewiduje też możliwość rozszerzania języka przez użytkownika, na potrzeby konkretnej aplikacji.

SVG udostępnia wszystkie podstawowe kształty graficzne, a więc linie, okręgi, wielokąty i różnego rodzaju krzywe. Pozwala na bogate formatowanie tekstu, łącznie z opisywaniem go na krzywej. Umożliwia stosowanie różnego rodzaju wypełnień, zarówno pełnym kolorem, jak i gradientowych, czy też wypełniania wzorcem rastrowym lub wektorowym. Obiekty można grupować, ustalać ich wzajemne położenie, przenikanie, stopień przezroczystości, czy też stosować do nich filtry graficzne -- standardowe lub samodzielnie definiowane. Bogactwo specyfikacji czyni więc z SVG pełnowartościowy język opisu grafiki wektorowej. Z drugiej strony implementacja całości specyfikacji jest trudna i pracochłonna. Do dziś, mimo kilku lat istnienia języka (choć dopiero przez rok w postaci oficjalnego standardu), nie powstała żadna implementacja, spełniająca w 100 procentach całą specyfikację.

Najpopularniejszą przeglądarką SVG jest w tej chwili Adobe SVG Viewer 3.0, działający na zasadzie wtyczki do przeglądarki WWW. Oferuje on stosunkowo dobry stopień realizacji specyfikacji. Brakuje jednak pełnego wsparcia dla modyfikacji dokumentu przez skrypty. Istnieją wersje dla przeglądarek pracujących pod kontrolą systemów operacyjnych Windows, MacOS i GNU/Linux (tylko Mozilla). Starsza wersja wtyczki (2.0) jest standardowo dostępna w niektórych nowszych wersjach Internet Explorera. Wtyczkę można ściągnąc bezpłatnie ze stron Adobe, choć oczywiście kod źródłowy nie jest dostępny.

Firma Adobe jest zdecydowanie liderem we wspieraniu rozwoju standardu SVG. Możliwość edycji dokumentów SVG, w tym także animacji, posiadają programy Adobe Illustrator i Adobe GoLive!. Podobne możliwości mają także najnowsze wersje konkurencyjnego programu CorelDraw. Obsługa SVG w tych najpopularniejszych obecnie programach do obróbki grafiki wektorowej dobrze rokuje przyszłości języka.

Możliwość eksportu grafiki w formacie SVG jest dostępna także w najnowszych wersjach większości darmowych programów graficznych, wchodzących w skład popularnych dystrybucji systemu Linux, takich jak np. Sketch czy Kontour (część pakietu KOffice). Zwykle gorzej jest z poprawnym odczytywaniem dokumentów SVG. Pozytywnie na tym tle wypada będący częścią projektu GNOME program Sodipodi, który wybrałem jako podstawowe narzędzie edycyjne dla tworzonego przeze mnie systemu. Więcej informacji o wykorzystaniu Sodipodi znajduje się w p. 3.6.

Innym ważnym projektem związanym z implementacją SVG jest projekt Batik, prowadzony przez Apache Foundation. Batik to zestaw bibliotek w Javie, na podstawie których zbudowano między innymi najlepszy (przynajmniej z dostępnych bezpłatnie) rasterizer SVG, a także przeglądarkę. Najnowsza dostępna wersja przeglądarki Batik, 1.5, w chwili pisania pracy znajduje się jeszcze w fazie beta, niemniej jednak oferuje najpełniejszą realizację specyfikacji. Ograniczenia związane są głównie z tym, że niestety Batik jest tylko przeglądarką SVG, a więc nie wspiera wzajemnego zagłębiania dokumentów SVG, XHTML, czy MathML. Bardziej obiecujący pod tym względem jest projekt Mozilla SVG, czyli implementacja SVG bezpośrednio w przeglądarce Mozilla. Niestety, w tej chwili nie rozwija się on zbyt dynamicznie i implementowana jest poprawnie tylko niewielka część specyfikacji.

Dostępnych jest wiele innych narzędzi, zarówno komercyjnych, jak i darmowych. Są wśród nich zarówno przeglądarki, edytory, narzędzia do generowania SVG po stronie serwera WWW, jak i wiele konwerterów z innych formatów, np. z dokumentów programu AutoCAD czy map cyfrowych. W miarę pełną i aktualną listę implementacji można znaleźć na stronach W3C [14].

Standard SVG jest nadal rozwijany. W tej chwili dostępne są już wersje 1.1 i 1.2 specyfikacji. Wprowadzają one między innymi modularyzację SVG, która ma umożliwić łatwiejszą implementację podstawowego zakresu funkcji, głównie z myślą o urządzeniach przenośnych.

Można by chyba zaryzykować stwierdzenie, że SVG trafił w potrzeby rynku, a mimo początkowych trudności z implementacją, przekroczona została pewna masa krytyczna, powyżej której będzie on zyskiwał coraz większą popularność i będzie powstawać coraz więcej implementacji.

Stosowanie w projekcie standardowych rozwiązań pozwoliło mi na duże uproszczenie implementacji, przez możliwość korzystania z gotowych elementów, zarówno programów, jak i bibliotek programistycznych. Miałem także komfort korzystania ze sprawdzonych rozwiązań, bez ryzyka popełnienia poważnych błędów projektowych, np. przy specyfikowaniu formatów używanych dokumentów. Cenną cechą rozwiązań opartych na XML jest prostota ich modyfikacji, rozszerzania, łączenia z innymi systemami i dostosowywania do nowych zadań.

3.3   System SZARP -- źródło danych

Wykonana implementacja systemu wizualizacji korzysta z systemu SZARP jako źródła danych. I mimo, że jednym z założeń projektu jest możliwość współpracy z jak najszerszą klasą systemów typu SCADA i innych, to krótkie omówienie budowy i cech systemu SZARP jest istotne dla wyjaśnienie niektórych przyjętych rozwiązań, zwłaszcza dotyczących wykonanej implementacji. Poza tym pozwala to na zaprezentowanie przykładowego systemu SCADA.

Geneza systemu sięga lat 80-tych [8]. W roku 1983 powstała firma Praterm, zajmująca się automatyzacją ciepłownictwa. Początkowo wykorzystywała urządzenia elektromechaniczne, a od 1989 roku mikroprocesorowe sterowniki przemysłowe. Wkrótce okazało się, że dla potrzeb prowadzenia różnego rodzaju analiz potrzebna jest rejestracja wartości parametrów, charakteryzujących przebieg procesu technologicznego w ciepłowni. W roku 1991 powstał pierwszy program, napisany w Turbo Pascalu pod DOS-em, rejestrujący dane zbierane przez łącza RS-232. W miarę rozwoju do systemu dodawano kolejne aplikacje, SZARP został też przeniesiony na platformę UNIX (kolejno były to systemy USL Unix SVR4.2 firmy Consensys, Novell UnixWare 1.1 i 2.03, SCO UnixWare 2.1). W roku 1994 Piotr Branecki i Lucjan Przykorski obronili na Wydziale Elektroniki i Technik Informatycznych Politechniki Warszawskiej pracę ,,System zbierania danych i sterowania wolnozmiennych procesów technologicznych o rozproszonych punktach kontrolno-pomiarowych'', dotyczącą SZARP-a. W 1996 roku nie posiadający dotychczas nazwy system został oficjalnie nazwany ,,System Zbierania, Archiwizacji i Prezentacji Danych SZARP v2.0'' (wersja 1.0 to wersja pracująca pod DOS-em). W roku 1998 system przeniesiono na Linuksa i oznaczono numerem wersji 2.1. W tej chwili system jest zainstalowany w 23 ciepłowniach w 20 miastach w całej Polsce.

System nigdy nie był oferowany jako samodzielny produkt. Zawsze stanowił część kompleksowej oferty modernizacji ciepłowni i służył do osiągnięcia określonych efektów ekonomicznych, takich jak zmiejszenie zużycia opału czy energii elektrycznej.




Rysunek 3.2: Uproszczony schemat architektury systemu SZARP


Obecnie w architekturze systemu można wyróżnić kilka warstw [4]. Najniższą stanowią mikroprocesorowe programowalne sterowniki przemysłowe. Wykonują one programy technologiczne, bezpośrednio sterujące przebiegiem procesu technologicznego. Poza tym udostępniają w postaci cyfrowej informacje o wartościach kontrolowanych parametrów.

Dane ze sterowników są transmitowane za pomocą łączy szeregowych różnego typu lub łączy radiowych do wieloportowej karty podłączonej do komputera klasy PC -- serwera systemu SZARP. Jest to maszyna średniej klasy, wyposażona zwykle w 64 do 256 MB pamięci RAM i dysk (najczęściej SCSI) o pojemności kilku do kilkudziesięciu GB. Jedynym specjalnym wyposażeniem komputera jest karta wieloportowa, zwykle typu Specialix lub Moxa, czasem także pyłoszczelna obudowa i specjalna przemysłowa myszka i klawiatura. Związane jest to z dużym zapyleniem ciepłowni. Dodatkowym wyposażeniem jest często UPS. Komputer działa pod kontrolą systemu operacyjnego RedHat Linux.

Do każdego z obsługiwanych portów szeregowych przyporządkowany jest program, zwany demonem linii. Podstawowym jego zadaniem jest zmiana formatu danych ze specyficznego dla protokołu obsługiwanego przez dany sterownik do wspólnego dla całego systemu. Przetworzone dane są wstawiane przez demony linii do segmentu pamięci dzielonej, utworzonego przez program należący do następnej warstwy systemu -- centralny proces uśredniająco-koncentrujący.

Na danym komputerze istniej tylko jeden taki proces. Zbiera on dane wstawiane do pamięci dzielonej przez demony linii, wylicza średnie kroczące oraz tzw. parametry definiowalne (czyli wyliczane na podstawie innych) oraz udostępnia te dane procesom wyższych warstw, także poprzez pamięć dzieloną. Synchronizacja dostępu do segmentów pamięci dzielonej odbywa się za pomocą semaforów, w klasycznym schemacie czytelników i pisarzy.

Kolejnym istotnym elementem systemu jest program zapisujący dane do bazy. Co 10 minut zapisuje on odczytane z segmentu pamięci procesu uśredniającego średnie 10-minutowe do bazy w formacie dBase IV. Przeliczane i zapisywane są także średnie 8-godzinne, dobowe, tygodniowe i miesięczne. Program wyposażony jest w funkcje automatycznego naprawiania uszkodzonych plików i odtwarzania danych z  tworzonych kopii zapasowych. Ilość generowanych przez system danych nie jest zbyt duża. Rejestracja jednego parametru przez okres jednego roku wymaga stu kilkudziesięciu kilobajtów miejsca na dysku. W obsługiwanych systemach parametrów jest zwykle kilkaset do kilku tysięcy.

Interesującą funkcją programu jest system BODAS (Baza Ogólnopolska Danych Archiwalnych Systemu SZARP). Dane z wszystkich posiadających połączenie z Internetem ciepłowni są transmitowane do serwera w siedzibie firmy Praterm w Warszawie. Przesyłane są tylko dane dodane lub zmodyfikowane. Rozwiązanie działa zarówno dla ciepłowni posiadających łącza SDI (wtedy aktualizacja następuje co 10 minut), jak i przy pomocy dostępu przez modem (w tym wypadku aktualizacja zwykle raz na dobę). System BODAS pozwala na przeglądanie danych archiwalnych z wszystkich obsługiwanych systemów w siedzibie firmy Praterm oraz znacząco zwiększa szansę odzyskania większości danych w przypadku np. awarii dysku w serwerze. BODAS jest wykorzystywany także lokalnie, jeśli zachodzi potrzeba przeglądania danych z bazy serwera na innym komputerze, np. drugim serwerze czy terminalu linuksowym.

Wszystkie pozostałe programy wchodzące w skład systemu korzystają z danych przygotowywanych albo przez proces uśredniający (i odczytywanych z pamięci dzielonej), albo też odczytywanych z bazy danych.

Do programów tych należą różnego rodzaju programy analizujące i optymalizujące, działające w tle. Do innej klasy należą programy służące do prezentacji danych, zarówno archiwalnych jak i bieżących. Jednym z takich programów jest też tworzony w ramach pracy magisterskiej system wizualizacji.

Część z programów prezentacji danych została napisana w C, z wykorzystaniem bibliotek Motiff. Są one uruchamiane albo bezpośrednio na serwerze, albo na terminalu linuksowym, albo z terminala działającego pod kontrolą system operacyjnego Windows, z wykorzystaniem emulatora X terminala. Część nowszych programów jest napisana w języku skryptowym Tcl/Tk, dostępnym zarówno pod Linuksem, jak i pod Windows.

Uproszczony schemat architektury systemu SZARP przestawia rys. 3.2.

W tego typu dość skomplikowanym systemie istotna jest łatwość i elastyczność konfiguracji. O ile zastosowanych w systemie SZARP rozwiązań jest dość wygodna (np. konfiguracja na wszystkich serwerach i terminalach w obrębie jednej ciepłowni może być jednakowa), to ogólnie konfiguracja systemu jest dość skomplikowana, a niektóre rodzaje modyfikacji są żmudne i pracochłonne. Zmiana tego faktu będzie prawdopodobnie w najbliższym czasie jeden z podstawowych kierunków rozwoju systemu.

W moim projekcie korzystam z bibliotek, będących częścią systemu SZARP. Jedną z nich jest prosta biblioteka umożliwiająca zbierania i przechowywanie informacji o ważnych zdarzeniach w systemie, druga to biblioteka obsługująca pliki konfiguracyjne systemu SZARP. Obie biblioteki są mojego autorstwa (chociaż druga korzysta z wcześniej napisanego kodu). Mogą one być używane niezależnie od pozostałych części SZARP-a i zostały dołączone do kodu źródłowego projektu.

3.4   Biblioteka serwera HTTP

Zarówno serwer parametrów, jak i procesor dokumentów są serwerami HTTP. Pojawiło się więc pytanie, w jaki sposób zrealizować tą część funkcjonalności programów. Nie istnieją w tej chwili darmowe biblioteki serwerowe HTTP. Należało więc albo skorzystać z gotowych rozwiązań przez napisanie programów w postaci skryptów CGI lub modułów serwera Apache, albo też stworzyć własne rozwiązanie.

Zdecydowałem się na to drugie rozwiązanie, ze względu na to, że nie chciałem wymuszać na użytkownikach instalacji i konfiguracji serwera Apache. Uznałem, że lepiej będzie, jeśli oba programy będą miały postać samodzielnych aplikacji.

Niejako więc przy okazji, jako produkt uboczny pracy, powstała biblioteka serwerowa HTTP, napisana w C++. Wybór języka został podyktowany wydajnością i koniecznością współpracy z serwerem parametrów, który musi czytać dane z pamięci dzielonej (a więc najwygodniej było go napisać w C lub C++). Zaś napisanie biblioteki w C++, a nie C, pozwoliło na stworzenie obiektowego interfejsu, łatwiejszego w użyciu i modyfikacji. Podstawową wadą użycia języka tak niskiego poziomu jest oczywiście podatność na trudno wykrywalne błędy związane z zarządzaniem pamięcią. Ze względów wydajnościowych oraz ewentualnej przenośności biblioteki nie wykorzystywałem zaawansowanych funkcji języka C++, takich jak szablony (ang. templates), wielokrotne dziedziczenie czy wyjątki.

Protokół HTTP jest dość rozbudowany. Nie była moim celem ani ambicją pełna implementacja protokołu. Jedynym kryterium doboru implementowanych funkcji HTTP była ich użyteczność dla zastosowania w moim projekcie i bezproblemowa współpraca biblioteki z najczęściej spotykanymi na rynku przeglądarkami, głównie Internet Explorer, Netscape Navigator, Mozilla (w różnych odmianach) i Lynx.

Oto krótka lista implementowanych funkcji protokołu HTTP: Ta lista nie wyczerpuje wymagań, jakie specyfikacja protokołu HTTP [7] stawia wobec implementacji bezwarunkowo zgodnych (ang. unconditionally compliant) lub warunkowo zgodnych (ang. conditionally compliant). Na przykład specyfikacja wymaga, aby serwer HTTP/1.1 obsługiwał także żądania HEAD. Poza tym moja implementacja jest mniej rygorystyczna niż zakłada specyfikacja i uznaje za poprawne niektóre żądania klienta, które w świetle specyfikacji poprawne nie są (np. żądania GET HTTP/1.1 bez nagłówka Host).

Biblioteka nie ma właściwie żadnego wsparcia dla obsługi schowków, zarówno po stronie serwera, serwera proxy, jak i przeglądarki. Wynika to ze specyfiki projektu, w którym przecież prezentowane dane i tak co kilka sekund się zmieniają, nie ma więc potrzeby ani sensu ich przechowywać. Jedynym wsparciem dla schowka po stronie klienta jest obsługa nagłówka Expire. Z jednej strony służy on do wymuszenia na przeglądarce ściągania z serwera nowych wersji stron zawierających dynamiczne dane, z drugiej strony może poinformować przeglądarkę, że powinna trzymać w schowku niektóre dane, np. statyczne elementy grafiki stron WWW.

Biblioteka obsługuje nie tylko zwykłe połączenia HTTP, ale także połączenia tunelowane z użyciem protokołów SSL (Secure Sockets Layer) w wersji 2 i 3, oraz TLS 1.0 (Transport Layer Security). Korzysta w tym celu z biblioteki OpenSSL [11]. Obsługa szyfrowanych połączeń w połączeniu z obsługą autoryzacji HTTP Basic pozwala na zapewnienie pełnej kontroli dostępu i poufności przesyłanych danych.

Klasa odpowiedzialna za autoryzację użytkowników jest oczywiście elementem wymiennym. Klasa używana standardowo w projekcie zapewnia kontrolę dostępu na poziomie elementów ścieżki dostępu do żądanego zasobu. Przez elementy ścieżki dostępu rozumiem fragmenty ścieżki oddzielone znakami ukośnika /. Zazwyczaj będą to katalogi i pliki, w serwerze parametrów będą to grupy parametrów i parametry (zobacz opis serwera parametrów w rozdziale 3.5). Każdemu elementowi może być przyporządkowana dowolna liczba użytkowników, którym pozwalamy na dostęp do elementu i wszystkich elementów podrzędnych (a więc np. do podkatalogów i plików w katalogu lub wszystkich parametrów z grupy). Opis praw dostępu trzymany jest w jednym pliku, o formacie opisanym w dodatku D.1.3. Poza nazwą użytkownika wymagane jest także hasło. Sprawdzanie użytkownika i  hasła przeprowadza się z użyciem systemowych mechanizmów PAM (Pluggable Authentication Modules), co pozwala na użycie różnych mechanizmów autoryzacji bez modyfikacji w programie. Powinna być to jednak autoryzacja korzystająca z nazwy użytkownika i hasła, gdyż taki schemat jest używany przez protokół HTTP.

Autoryzacja jest wymagana tylko przy próbach zapisu, czyli jeżeli w ścieżce dostępu do zasobu pojawi się opcja put. Jest więc zdefiniowany tylko jeden rodzaj operacji na zasobie (nie ma oddzielnych praw dla odczytu, zapisu itp.).

Przeglądarki po pierwszej autoryzacji użytkownika wysyłają nazwę użytkownika i hasło przy każdym następnym odwołaniu do strony. Aby zapobiec sytuacji, w której użytkownik po przeprowadzonej autoryzacji zostawia komputer bez opieki bez wyłączania przeglądarki lub zmiany strony, po zadanym czasie autoryzacja wygasa. Jest to realizowane przez wysyłanie fałszywej informacji o nieudanej autoryzacji, jeżeli poprzedni dostęp do strony odbył się dawniej niż zadany czas temu. Użytkownik musi ponownie wprowadzić nazwę użytkownika i hasło, co pozwala stwierdzić, czy z przeglądarki nadal korzysta osoba uprawniona.

Taka implementacja wynika z wymagań serwera parametrów. Jeśli potrzebny byłby inny system kontroli dostępu, to konieczne byłoby przedefiniowanie klasy odpowiedzialnej za kontrolę dostępu.

Dodatkowo, biblioteka dość niestandardowo obsługuje niektóre postacie ścieżek dostępu podawane przez klienta. Za ścieżkę dostępu uznawana jest tylko część do napotkania znaku @. To co jest po nim (a przed opcjami, czyli znakiem ?) jest traktowane specjalnie -- jako nazwa atrybutu elementu XML. Zachowanie to, mimo że niestandardowe, nie powinno przeszkadzać w aplikacjach nie korzystających z niego, gdyż zwykle ścieżki dostępu do zasobów w sieci WWW nie zawierają znaków @.

Biblioteka ma klasyczną architekturę serwera wielowątkowego. Główny wątek nasłuchuje na zadanym porcie. Po zaakceptowaniu połączenia przekazuje je do wątku obsługującego połączenie. Wątków takich może być nie więcej niż liczba podana w konfiguracji serwera. Wątki tworzone są na żądanie, ale tylko raz -- wątek, który zakończył obsługę połączenia jest przenoszony do puli wolnych i budzony ponownie w razie potrzeby. Jest to rozwiązanie szybsze niż tworzenie nowego wątku przy każdym nowym połączeniu.

Wątki obsługują połączenia asynchronicznie, za pomocą funkcji select(). W pliku konfiguracyjnym można określić tzw. timeout, czyli czas, po jakim połączenie jest zamykane w przypadku braku aktywności. Jeżeli klient sobie tego zażyczył, obsługiwane są połączenia typu Keep-Alive (domyślne dla protokołu HTTP w wersji 1.1). Połączenia takie nie są zrywane po zakończeniu transmisji danych, co pozwala na przesyłanie dalszych danych do przeglądarki za pomocą tego samego połączenia TCP/IP, bez konieczności negocjowania nowego [7].

Biblioteka implementuje prostą strategię zapobiegania wykorzystaniu całej puli wątków przez połączenia typu Keep-Alive. Jeżeli liczba wątków aktywnych przekroczy 80 procent maksymalnej, to po zakończeniu transmisji danych połączenia się zamyka.

Mimo formalnego braku zgodności biblioteki z wymaganiami stawianymi przez specyfikację protokołu HTTP, starałem się, aby zachowanie biblioteki było czytelne dla aplikacji klienckich, między innymi przez ustawianie odpowiednich kodów błędów (w tym oznaczających brak implementacji danej funkcji).

Najważniejsze klasy wchodzące w skład biblioteki to: Przykładowy program korzystujący z biblioteki mógłby wyglądać tak (opuszczono kontrolę błędów i niektóre mniej istotne fragmenty):

class MyContentHandler : public AbstractContentHandler {
       public :
              XSLTContentHandler(void) { };
              virtual void create(HTTPRequest *req, HTTPResponse *res)
              {
                     res->content = strdup("To jest odpowiedź");
                     res->content_length = strlen(res->content);
              }
              virtual int set(HTTPRequest *req) { return 0; };
};

int main(int argc, char **argv)
{
       ConfigLoader *cloader;
       Server *server;
       ConnectionHandler *ch;
       AbstractContentHandler *conh;

       // Wczytaj informacje z pliku konfiguracyjnego i wiersza poleceń.
       cloader = new ConfigLoader("plik.konf", "sekcja_w_pliku_konf",
                     &argc, argv);
       
       // Utwórz obiekt odpowiedzialny za odpowiadanie na żądania klienta
       conh = new MyContentHandler();
       
       // Inicjowanie obsługi połączeń, ustaw timeout dla połączeń
       ch = new ConnectionHandler(conh, cloader->getInt("timeout", 30));
       
       // Inicjowanie serwera, argumentami są port, obiekt obsługujący
       // połączenia oraz maksymalna liczba połączeń
       server = new Server(cloader->getInt("port", 8081), 
                     ch, 
                     cloader->getInt("max_cons", 20));
       // Uruchom serwer
       server->start();
}
Stworzona biblioteka miała służyć konkretnym celom -- implementacji programów wchodzących w skład mojego systemu -- i dobrze spełnia swoje zadanie, współpracując bez problemów z przeglądarkami oraz bibliotekami klienckimi HTTP (takimi jak NanoHTTP wchodząca w skład biblioteki libxml2). Przy okazji powstało narzędzie ogólniejsze, niezależne od reszty projektu, mogące służyć do implementacji innych prostych, niewielkich serwerów HTTP. Zaletą biblioteki jest proste API, małe rozmiary i obsługa transmisji szyfrowanych. Główną wadą jest niewielki zakres zaimplementowanej funkcjonalności protokołu HTTP i specyfika niektórych rozwiązań (głównie kontroli dostępu).

3.5   Serwer parametrów

Serwer parametrów jest jednym z istotniejszych elementów całego systemu. Zapewnia on łącze między bazowym systemem typu SCADA, związanym z konkretną architekturą sprzętową, a wyższymi warstwami, wykorzystującymi technologie oparte na XML. W opisie skoncentruję się na wykonanej implementacji, przystosowanej do współpracy z systemem SZARP, a dopiero na końcu poświecę kilka słów możliwościom dostosowywania programu do współpracy z innym źródłem danych.

Ze względu na konieczność korzystania z pamięci dzielonej oraz napisanej w C++ biblioteki serwerowej (p. 3.4) serwer parametrów napisano w prostym C++, bez obsługi wyjątków (co pozwala na tworzenie przez kompilator szybszego i bardziej zwartego kodu).

Informacje o parametrach są czytane z pamięci dzielonej procesu uśredniająco-koncentrującego systemu SZARP. W tym celu przy starcie program czyta pliki konfiguracyjne systemu SZARP i buduje wewnętrzną reprezentację zbioru obecnych w systemie parametrów w postaci drzewa XML3. Wartości parametrów, o ile są dostępne, są czytane tylko na żądanie klientów, ale nie częściej niż co zadany czas odświeżania (standardowo w systemie SZARP jest to 10 sekund) -- wartości parametrów mogą więc być buforowane przez program. Przed udostępnieniem informacji o wartościach parametru muszą one zostać przekształcone do postaci tekstowej zgodnie z dodatkowymi informacjami uzyskanymi z plików konfiguracyjnych (a więc np. liczbą miejsc po przecinku czy też reprezentacją wartości w postaci napisów ,,Tak'' i ,,Nie'').

Segment pamięci dzielonej jest przy każdym odczycie na nowo podłączany do przestrzeni adresowej programu. Jest to rozwiązanie wolniejsze, ale pozwala na przetrwanie bez szkody ewentualnych przerw w działaniu procesu udostępniającego dane. Synchronizacja dostępu do pamięci dzielonej jest wykonywana za pomocą semaforów.

W systemie SZARP parametry przechowuje się w jednowymiarowej tablicy. Jednak dla potrzeb różnego rodzaju programów prezentujących ich wartości, grupuje się je logicznie w strukturę drzewiastą. Strukturę tą wyznaczają pełne nazwy parametrów, składające się z części oddzielonych dwukropkami. Struktura drzewiasta jest budowana na podstawie wspólnych części nazw. Np. parametry Kocioł 1:Sterownik:temperatura zadanaKocioł 1:Sterownik:aktualne wysterowanie falownika rusztu można traktować jako liście w drzewie, których ojcem jest węzeł Sterownik, będący synem węzła Kocioł 1, który jest synem węzła głównego (korzenia) drzewa. Taka struktura logiczna ułatwia zarządzanie i przeglądanie informacji o parametrach, umożliwiając np. automatyczne tworzenie zestawień parametrów dotyczących danego kotła.

Naturalnym rozwiązaniem było przeniesienie tej struktury także do serwera parametrów. Ponieważ jednak serwer parametrów nie ma być związany z konkretnym systemem SCADA oraz ponieważ takie rozwiązanie jest bardziej naturalne z punktu widzenia przeglądarek WWW, zdecydowałem się na zastąpienie znaku : znakiem /, zwłaszcza że dwukropek w URI4 pełni już inną funkcję -- poprzedza numer portu. W razie potrzeby z takiej postaci nazwy parametru można oczywiście bez problemu uzyskać nazwę oryginalną (i to właśnie robi program, wyszukując zadanych parametrów). Nazwy w tej postaci przekazywane są bezpośrednio do serwera parametrów w żądaniach HTTP. Tak więc, aby uzyskać informację o jednym z poprzednio prezentowanych przykładowych parametrów, należałoby wpisać w przeglądarce adres http://adres.serwera:port/Kocioł 1/Sterownik/temperatura zadana.

Z każdym parametrem związanych jest kilka informacji. Właściwie zawsze będzie to nazwa (choć ta określana jest już przez ścieżkę dostępu) oraz aktualna wartość, zwykle także symbol jednostki, w jakiej wyrażona jest wartość parametru. W systemie SZARP dodatkowo mogą to być różne postacie skrócone nazwy, numer rekordu w bazie danych, indeks parametru w pamięci dzielonej. W związku z reprezentacją parametrów w postaci drzewa XML, naturalne było reprezentowanie tych informacji jako atrybutów elementu. Aby więc uzyskać informację o wartości parametru, należałoby podać adres w postaci: http://adres.serwera:port/Kocioł 1/Sterownik/temperatura zadana@value.

Inne możliwe nazwy atrybutów to unit (nazwa używanej jednostki), short_name (skrócona nazwa parametru), full_name (pełna nazwa, z dwukropkami), ipc_ind indeks parametru w pamięci dzielonej i  prec -- ilość miejsc po przecinku w reprezentacji parametru. Użycie znaku @ jest zgodne z notacją dostępu do atrybutów elementów w wyrażeniach XPath. Taki sam efekt można by uzyskać stosując do całego dokumentu udostępnianego przez serwer parametrów wyrażenie /Kocioł 1/Sterownik/temperatura zadana[@value] (z dokładnością do spacji).

Spacje stanowią problem, ponieważ normalnie nie mogą wchodzić w skład zapytania przekazywanego do serwera. Niektóre przeglądarki zastępują spacje odpowiednimi sekwencjami znaków %kod. Niestety nie wszystkie potrafią to robić. Problem stanowią także niektóre inne znaki, np. znak ukośnika /, który w systemie SZARP może występować w nazwie parametru, natomiast w URI ma specjalną funkcję. Podobny problem występuje wtedy, gdy w nazwie parametru występują polskie literki. Trudno przewidzieć czy i jak (np. w jakim kodowaniu) zostaną przekazane przez przeglądarkę.

W związku z tym przy podawaniu zapytania do serwera znaki takie jak spacja, ukośnik itp. można zastąpić znakiem podkreślenia. Zaś polskie litery można zastąpić ich angielskimi odpowiednikami (ą przez a itp.). Dopuszczalne jest także kodowanie w postaci %kod (polskie litery w kodowaniu ISO-8859-2). Przykładowe ścieżki mogą więc mieć postać http://adres.serwera:port/Kociol_1/Sterownik/temperatura_zadana@value.

Dokumenty generowane przez serwer parametrów mają służyć głównie jako dane wejściowe dla procesora XSLT, muszą więc być dokumentami XML. Przydatna byłaby jednak także możliwość bezpośredniego dostępu do informacji o parametrach z przeglądarki, a więc przekazywanie informacji w postaci dokumentów HTML. Rodzaj generowanego dokumentu można wybrać przez podanie w ścieżce dostępu opcji output, która może przyjąć wartość xml, html lub text. W tym ostatnim przypadku generowany jest także dokument XML, ale z opisem typu zawartości text/plain, co pozwala na bezproblemowe wyświetlenie go także w przeglądarkach nie obsługujących XML.

Domyślnie (bez podania opcji output) generowany jest dokument HTML zawierający dowiązania do nadrzędnego węzła drzewa i węzłów lub parametrów podrzędnych (jeżeli wyświetlamy informacje o grupie parametrów) lub opis parametru z wartościami atrybutów (jeżeli podana ścieżka dostępu identyfikuje parametr).

Jeśli żądamy informacji o atrybucie, to domyślnie generowany jest dokument XML. Jeżeli podaliśmy ścieżkę do jakiegoś węzła w drzewie i opcję output=xml, to otrzymamy dokument zawierający poddrzewo z korzeniem w podanym węźle.

Tak więc po wpisaniu http://adres.serwera:port będziemy mogli rozpocząć przeglądanie parametrów w postaci HTML od głównego węzła drzewa parametrów, a wpisując http://adres.serwera:port/Kociol_1?output=xml otrzymamy informację o wszystkich parametrach dotyczących kotła 1 w postaci dokumentu XML.

Poza udostępnianiem informacji o wartościach parametrów, serwer parametrów ma też umożliwiać sterowanie procesem przez zadawanie wartości parametrów. Ponieważ program obsługuje tylko żądania HTTP GET, więc przekazywanie zadanej wartości parametru odbywa się przez użycie opcji o nazwie put. Ze względu na wymagania bezpieczeństwa, opisane w p. 2.9, wymaga to autoryzacji użytkownika i użycia połączenia szyfrowanego, za pomocą SSL. Można więc zadać wartość parametru wpisując w przeglądarce adres https://adres.serwera :port_ssl/Kociol_1/Sterownik/temperatura_zadana@value?put=67.3. Po zaakceptowaniu przez przeglądarkę certyfikatu serwera i podaniu przez użytkownika odpowiedniego identyfikatora i hasła serwer parametrów wstawia do pamięci dzielonej procesu uśredniającego żądaną wartość. Przekazanie jej do sterownika przemysłowego jest już zadaniem systemu SZARP.

Dzięki możliwości generowania informacji w formacie HTML serwer parametrów, jako program paramd, stał się samodzielnym i dość przydatnym elementem systemu SZARP. Pozwala na zdalne sprawdzanie wartości parametrów bez potrzeby posiadania specjalizowanego oprogramowania klienckiego. Instalacja programu nie wymaga żadnych zmian w konfiguracji systemu. Domyślnie przyjmowane wartości opcji konfiguracyjnych zapewniają sprawne działanie. Poza tym wykorzystanie go jako interfejsu dla innych aplikacji systemu pozwoliłoby w przyszłości na rozwiązanie problemu dostępu jednocześnie do parametrów zbieranych przez różne serwery SZARP. Program jest zainstalowany i działa w około 10 ciepłowniach w całej Polsce, w tym tylko w jednej jako część całego systemu wizualizacji -- w pozostałych samodzielnie.

 
Czas obsługi żądania dotyczącego pojedynczego parametru na komputerze z procesorem z zegarem około 1 GHz wynosi poniżej 1 milisekundy, a w przypadku wysyłania drzewa informacji o wszystkich parametrach np. ciepłowni w Bytowie (około 100 parametrów, wielkość pliku wyjściowego 18 KB) wynosi około 5 ms. Wartości te mierzono przy użyciu lokalnego interfejsu sieciowego, a więc bez opóźnień związanych z przesyłaniem przez sieć.

Dodatek D.1 zawiera dokumentację użytkownika programu, a B.1 dokładny opis formatów generowanych dokumentów XML.

 
Dostosowanie programu do innego źródła danych powinno być dość proste. Jedynym wymaganiem jest posiadanie przez parametry nazwy, unikatowej w obrębie pojedynczej instalacji, która może być zamieniona na jednoznaczny identyfikator liczbowy. Należałoby napisać nową implementację abstrakcyjnej klasy ParamLoader, która jest odpowiedzialna za wczytanie informacji konfiguracyjnych o parametrach i utworzenie drzewa parametrów, oraz klasy ParamReader, definiującej metody update, getValuesetValue (odpowiedzialne odpowiednio za odświeżenie informacji o wartościach parametrów, pobranie i ustawienie wartości). Moglibyśmy także chcieć generować inną postać dokumentów HTML, co wymagałoby przedefiniowania jednej metody w klasie ParamTree.

3.6   Tworzenie schematów.

3.6.1   Format dokumentów ISL

Tak jak już napisałem wcześniej, w p. 3.1, danymi prezentowanymi przez mój system są schematy, czyli rysunki (dokumenty) zapisane w SVG, wzbogacone o informacje konieczne do reprezentowania wartości parametrów. Ten zestaw rozszerzeń nazwałem roboczo Industry Schema Language, w skrócie ISL. Określenia dokumenty ISL używam także ogólnie do określenia schematów, w przeciwieństwie do dokumentów SVG, które mogą być jedną z form prezentacji wygenerowaną ze schematów.

Dla potrzeb projektu zdefiniowałem przestrzeń nazw XML, o następującym URI:
http://www.praterm.com.pl/ISL/params. Dalej do identyfikacji tej przestrzeni nazw używam prefiksu isl, choć sam prefiks ma znaczenie tylko w powiązaniu z URI i może być dowolny [17].

Podstawową formą prezentowania wartości parametrów jest reprezentacja tekstowa, a więc umieszczanie na rysunku tekstowej informacji o wartości parametru. Realizowane jest to przez dodanie do elementu tekstowego atrybutu isl:uri, którego wartością jest pełna ścieżka dostępu do atrybutu parametru (w postaci opisanej w p. 3.5). Użycie takiej konstrukcji oznacza, że w dokumencie wyjściowym zawartość elementu XML należy zastąpić przez tekstową reprezentację wartości atrybutu. Przykładowy dokument ISL, który po przetworzeniu będzie zawierał napis z wartością parametru, mógłby więc wyglądać następująco:

<?xml version="1.0" standalone="yes"?>
<svg
   width="100"
   height="100"
   xmlns:isl="http://www.praterm.com.pl/ISL/params"
   xmlns="http://www.w3.org/2000/svg">
  <text
     style="font-family:Helvetica; font-size:12.0;"
     x="10.0"
     y="20.0"
     isl:uri=
     "http://213.76.238.20:8081/Siec/Sterownik/temperatura_zewnetrzna@value"
     id="text01">Ten tekst zostanie zastąpiony przez wartość parametru</text>
</svg>
Obecność atrybutu id w elemencie, mimo że nie jest wymagana przez specyfikację SVG, jest konieczna w elementach zależnych od parametrów do działania automatycznego odświeżania parametrów (zobacz p. 3.7.1).

Specyfikowanie pełnej ścieżki dostępu do parametru pozwala na pełną przenośność dokumentów -- wygląd schematu nie zależy od miejsca, w którym jest on przetwarzany. Zaś włączenie do ścieżki także nazwy atrybutu pozwala na niezależność schematów od konkretnej implementacji serwera parametrów, gdyż nie wszystkie systemy muszą udostępniać ten sam zestaw atrybutów dla parametrów. Poza tym zazwyczaj informacja o aktualnej wartości nie jest jedyną, jaką chcemy wyświetlać. Zamiast np. wstawiać na stałe do schematu nazwy jednostek, bezpieczniej i bardziej uniwersalnie jest użyć atrybutu unit.

Ze względu na częste użycie kombinacji atrybutów wartość i jednostka zdefiniowano także wirtualny atrybut v_u, który oznacza wstawienie jako zawartości elementu wartości atrybutów valueunit, przedzielonych pojedynczą spacją.

Poza tekstową reprezentacją wartości parametrów chcielibyśmy mieć możliwość także innego typu reprezentacji wartości. Drugim dostępnym sposobem jest uzależnienie od wartości parametru wartości atrybutu elementu SVG, a więc np. rozmiarów czy położenia elementu. Efekt taki uzyskuje się przez zdefiniowanie w elemencie, poza atrybutem isl:uri także atrybutu isl:target. Jego wartością jest nazwa atrybutu, którego wartość ma być zastąpiona przez wartość atrybutu parametru. Dodatkowe atrybuty elementu SVG, isl:shift i isl:scale, pozwalają na przeskalowanie i przesunięcie tworzonej wartości. Wartość atrybutu, o nazwie będącej wartością atrybutu isl:target jest więc zastępowana przez wartość i × isl:scale + isl:shift, gdzie i oznacza wartość atrybutu parametru pobraną z serwera parametrów.

Na przykład, jeżeli chcemy uzależnić położenie elementu od wartości atrybutu parametru, przy czym element chcemy przesunąć w prawo od punktu (100, 100) o wartość atrybutu podzieloną przez 2, to kod elementu może wyglądać tak:

<rect
  x="100" y="100" width="50" height="50" style="fill:#FF0000"
  isl:uri=
  "http://213.76.238.20:8081/Siec/Sterownik/temperatura_zewnetrzna@value"
  isl:target="x" isl:scale="0.5" isl:shift="100"/>
Rysunek 3.3 przestawia przykład wykorzystania tych konstrukcji -- słupek rtęci w termometrze pokazuje wartość zależną od mierzonej temperatury. Dodatkowo temperatura jest wyświetlana w postaci tekstowej5.




Rysunek 3.3: Przykład wykorzystania atrybutów zależnych od wartości parametrów


Jeżeli rysowany schemat zawiera dowiązania, to zaleca się użycie w elemencie <a/> (oznaczającym dowiązanie) atrybutu isl:link-coords. Jego wartością są cztery współrzędne wyznaczające prostokąt -- obszar aktywny związany z dowiązaniem. Atrybut ten nie jest wykorzystywany przy prezentacji danych w postaci SVG (wtedy obszarem aktywnym jest element zawarty w elemencie <a/>). Niestety wyznaczenie pozycji i rozmiarów elementu SVG nie jest możliwe bez parsowania być może całego dokumentu. W związku z tym procesor XSLT przetwarzający schematy potrzebuje pomocy w wyznaczeniu pozycji dowiązania jeżeli jest generowany inny typ dokumentu (np. bitmapa), który sam takich informacji nie zawiera. Jeżeli atrybutu nie ma, to procesor próbuje obejść ten problem w inny sposób (więcej na ten temat w p. 3.7.1).

Zaprezentowany prosty zestaw rozszerzeń okazał się wystarczający do stworzenia schematów w ramach wykonanego wdrożenia systemu wizualizacji. W razie potrzeby można go łatwo rozszerzyć (np. o możliwość obrotu elementu zależnie od wartości parametru czy też uzależnienie od niej koloru elementu). Modyfikacje takie nie wymagają zmian w kodzie żadnej części systemu. Należy dodać jedynie obsługę nowych atrybutów (lub elementów) do szablonów XSLT. Prawdopodobnie szablony te będą modyfikowane w miarę pojawiania się zapotrzebowania na konkretne efekty wizualne. Wydaje się jednak, że zaprojektowany schemat rozszerzeń jest na tyle elastyczny, że powinien umożliwić realizację właściwie dowolnych efektów.

Rysunek 3.4 przedstawia bardziej złożony schemat, prezentujący ciepłownię w Bytowie6. Dokładny opis rozszerzeń ISL zawiera dodatek B.2.




Rysunek 3.4: Schemat ciepłowni w Bytowie z wartościami parametrów


3.6.2   Edytor SVG/ISL

Jedną z pożądanych cech systemu ma być możliwość graficznej edycji schematów (por. rozdz. 2.12). Zwłaszcza że dokumenty SVG, przez wykorzystanie krzywych, wypełnień gradientowych itp., są zbyt złożone do edycji ręcznej.

Jednym z powodów wybrania SVG jako języka do tworzenia schematów była możliwość korzystania z istniejących programów. Zależało mi, aby było to narzędzie darmowe. Po pierwsze dlatego, że w pozostałej części projektu używam bezpłatnego oprogramowania, szkoda więc byłoby, gdyby za możliwość wygodnej edycji schematów użytkownik miał płacić. Po drugie, użycie programów z dostępnym kodem źródłowym pozwala na zaprojektowanie rozszerzeń do edycji elementów z przestrzeni nazw isl, a więc związanych z parametrami.

Bezpłatne narzędzia istnieją, nie dorównują jednak takim programom jak np. Adobe Illustrator, uważany powszechnie za najlepszy program do edycji SVG (firma Adobe była jedną z pierwszych, które poważnie zajęły się implementowaniem SVG, jeszcze na długo przed tym, zanim stał się oficjalnym standardem).

Poszukiwania doprowadziły mnie do programu Sodipodi. Program jest rozwijany w ramach projektu Gnome, od 1999 roku. Jego autorem i głównym realizatorem jest Lauris Kaplinski, związany przejściowo między innymi z firmą Ximian, która zajmuje się rozwojem projektu Gnome. Wybór Sodipodi podyktowany został tym, że spośród dostępnych programów Open Source implementuje on największą część specyfikacji. W szczególności SVG jest dla niego formatem natywnym. Wiele innych programów pozwala tylko na eksport do SVG, co powoduje konieczność trzymania dwóch wersji schematów (oryginalny plik i wyeksportowany SVG) oraz problemy z obsługą rozszerzeń ISL.

Programowi Sodipodi sporo brakuje jeszcze do doskonałości. Nie obsługuje on całej funkcjonalności SVG. Brakuje mu między innymi filtrów i wypełnień wzorcem, nie ma wsparcia dla wielokrotnego użycia elementów (co może znacznie zmniejszać rozmiary pliku z obrazkiem). Ma trochę błędów w renderowaniu obrazków (choć da się każdy element narysować tak, żeby zarówno w Sodipodi, jak i w Adobe SVG był renderowany tak samo). Kłopotliwe dla polskiego użytkownika są problemy z polskimi znakami -- nie są one renderowane poprawnie i nie można ich bezpośrednio wprowadzać (trzeba korzystać z mechanizmu kopiuj/wklej X serwera lub edytować plik ręcznie).

Z drugiej strony program posiada na tyle bogaty i dobrze opracowany zestaw narzędzi, że pozwala na skupienie się na projektowaniu schematów, a nie na walce z samym programem, co zdarza się w wypadku innych narzędzi znajdujących się w początkowej fazie rozwoju. Program posiada też polską wersję językową.

Konieczność dodania do programu narzędzi pozwalających na edycję elementów ISL wiązała się z kilkoma problemami. Ponieważ Sodipodi jest projektem cały czas rozwijającym się, nie mogłem bezkarnie modyfikować programu w nadziei, że przygotowane przeze mnie łaty będą pasować do kolejnych wersji. Z drugiej strony nie chciałem się ograniczać do aktualnie dostępnej wersji programu, aby móc korzystać z nowości i usprawnień wprowadzanych w nowych wersjach.

Zdecydowałem się więc na formułę zmian, która pozwoliła na dołączenie moich poprawek do oficjalnej dystrybucji Sodipodi. Sodipodi w wersji 0.24 posiadał niedziałający edytor XML, który w założeniu miał pozwalać na dowolną edycję dokumentu, przez operowanie bezpośrednio na drzewie XML. Korzystając z zaprojektowanego wcześniej układu okienka edytora, napisałem kod odpowiedzialny za edycję drzewa. Działanie edytora wymagało także kilku zmian w innych fragmentach programu, np. związanych z obsługą innych niż SVG przestrzeni nazw. Przy okazji znalazłem i usunąłem kilka błędów. Napisany przeze mnie kod wysłałem autorowi programu i został on dołączony do oficjalnego kodu programu7.

Tworzenie schematu w programie Sodipodi polega więc na tworzeniu rysunku o wielkości odpowiadającej pożądanej wielkości schematu, za pomocą standardowych narzędzi dostępnych w wektorowych programach graficznych. Aby wstawić tekstową wartości parametru, należy najpierw utorzyć dowolny napis, w miejscu gdzie ma być wstawiona wartość. Po zaznaczeniu tego napisu otwieramy okno edytora XML (dostępne z menu kontekstowego prawego przyciska myszki, opcja Dialogs). W polu edycji atrybutów wciskamy przycisk Add i wpisujemy nazwę atrybutu (isl:uri) oraz wartość -- ścieżkę dostępu do atrybutu parametru. Należy się jeszcze upewnić, czy w głównym elemencie dokumentu znajduje się deklaracja przestrzeni nazw ISL, czyli atrybut o nazwie xmlns:isl i wartości http://www.praterm.com.pl/ISL/params. Jeśli go nie ma, należy go w analogiczny sposób dodać.

Podobnie przez dodawanie atrybutów do elementu w edytorze XML, ustawiamy zależność atrybutu od wartości parametru oraz pozycję dowiązania (zobacz p. 3.6.1).

Użyteczną cechą Sodipodi jest to, że do każdego elementu dołącza on unikatowy identyfikator w postaci atrybutu id, co jest niezbędne do działania automatycznego odświeżania wartości parametrów w schematach (szczegóły w p. 3.7.1).

Wersja Sodipodi znajdująca się obecnie (w chwili pisania pracy) w repozytorium CVS jest niestabilna. W związku z tym w projekcie używam własnej wersji, opartej na wersji 0.24 i częściowo 0.25, z kilkoma drobnymi poprawkami. Kod źródłowy tej wersji, oznaczonej przez mnie symbolem 0.25-isl jest obecny na dołączonej do pracy płycie CD.

Mimo że Sodipodi posiada jeszcze sporo błędów i niedociągnięć, jest dość wygodnym i funkcjonalnym narzędziem do tworzenia schematów. Za jego pomocą stworzone zostały wszystkie prezentowane w ramach projektu rysunki, między innymi schematy ciepłowni w Ełku i Bytowie. Szkoda tylko, że w ostatnich miesiącach tempo rozwoju projektu Sodipodi wyraźnie osłabło.

Przydatna byłaby w przyszłości możliwość dodawania wartości parametrów np. na zasadzie wyboru parametru z listy, zamiast wymaganego obecnie wpisywania nazwy parametru jako wartości odpowiedniego atrybutu. Wymagałoby to jednak poważnych ingerencji w kod programu, które nie mają sensu na obecnym etapie jego rozwoju.

3.7   Procesor dokumentów

3.7.1   Zadania procesora XSLT

Jądrem całego systemu wizualizacji jest serwer HTTP połączony z procesorem XSLT. Jego zadaniem jest przygotowywanie dokumentów prezentowanych oprogramowaniu klienckiemu. Dokumenty te są generowane na podstawie stworzonych przez użytkownika schematów i ewentualnie innych dokumentów oraz informacji o wartościach parametrów, pobieranych z serwera parametrów.

W najprostszym przypadku procesor ma za zadanie jedynie wstawić wartości atrybutów elementów pobranych z serwera parametrów do schematu, tworząc w ten sposób statyczny dokument SVG, reprezentujący stan procesu w chwili wygenerowania dokumentu SVG. Zadanie to może zrealizować stosunkowo prosty szablon, korzystający ze zdefiniowanej w XSLT funkcji document(), która pozwala na wstawienie do szablonu całości lub części innego dokumentu, być może pobranego wcześniej z sieci. W ten właśnie sposób procesor XSLT pobiera wartości dokumentów od serwera parametrów.

Możliwe były tu dwie strategie. Zwykle jeden schemat zawiera wiele odniesień do parametrów. Można było pobierać z serwera parametrów dokument z wartościami wszystkich parametrów, a potem wyłuskiwać wartości odpowiednich atrybutów za pomocą wyrażeń XPath. Drugie podejście, to pobieranie tylko wartości atrybutu, ale za to przy przetwarzaniu każdego odwołania do jakiegoś parametru. To drugie rozwiązanie jest nieco prostsze w implementacji. Poza tym nie ma znaczenia, czy wszystkie parametry pochodzą z tego samego serwera. Pierwsze rozwiązanie może oznaczać mniejszą liczbę koniecznych transmisji -- tylko po jednej z każdego serwera. Zwykle jednak ilość przesłanych danych i tak będzie większa, bo przesyłamy informacje o wszystkich parametrach, a na pojedynczym schemacie jest ich zwykle tylko kilkanaście.

Wybrałem więc rozwiązanie drugie, czyli oddzielną transmisję małej ilości danych dla każdego odwołania do parametru. Oczywiście, ponieważ całe rozwiązanie jest zapisane w formie szablonu XSLT, w razie potrzeby jest to proste do modyfikacji (gdyby okazało się, że jednak szybciej jest pobrać jednorazowo pełną informację o wartościach parametrów).

Statyczny SVG to jednak nie wszystko, co chcielibyśmy uzyskiwać od procesora dokumentów. Potrzebne są także schematy dynamiczne, przy czym odświeżaniu miałaby ulegać tylko część schematu związana z parametrami.

Opracowanie sposobu implementacji tego częściowego odświeżania dokumentów było jedną z trudniejszych koncepcyjnie części pracy. Wymyślone przeze mnie rozwiązanie wykorzystuje pewne specyficzne cechy SVG. Mianowicie, w SVG istnieją elementy <use/>. Element taki musi posiadać atrybut xlink:href8, będący wyrażeniem XPath wskazującym na inny element (zazwyczaj dowiązaniem do niego, wykorzystującym atrybut id). Zamiast elementów <use/> będzie rysowany element wskazywany przez atrybut. Oczywiście może to być także element z innego dokumentu, obecnego na innym serwerze.

Pierwsza część rozwiązania polega więc na rozdzieleniu fragmentów schematu zależnych od parametrów od reszty. Fragmenty zależne od parametrów są grupowane w jednym dokumencie, który nazywam dokumentem z definicjami. W drugim dokumencie znajdują się odwołania do tych definicji za pomocą elementu <use/> oraz pozostała, statyczna część schematu.

Poza tym w dokumencie tym procesor XSLT umieszcza skrypty w języku ECMAScript [6]. Skrypty te generowane są automatycznie. Co 10 sekund usuwają one kolejno wszystkie elementy <use/> i wstawiają je na nowo, ale ze zmienioną wartością atrybutu xlink:href. Zmieniona wartość wskazuje tak naprawdę na ten sam element, w tym samym dokumencie. Konieczna jest jednak drobna zmiana w ścieżce dostępu, żeby klient nie skorzystał przypadkiem z dokumentu obecnego w schowku (lokalnym lub serwera proxy).

Usunięcie i dodanie elementu <use/> zmusza oprogramowanie klienckie do ponownego pobrania informacji o wskazywanym elemencie z dokumentu z definicjami i narysowania go na nowo. Powoduje to wstawienie nowych wartości parametrów, pobranych z nowo utworzonego dokumentu z definicjami.

Oczywiście cały ten proces działa tylko przy założeniu, że oprogramowanie klienckie posiada odpowiednie wsparcie dla dynamicznej modyfikacji struktury dokumentu przez skrypty (zgodnie ze specyfikacją SVG). Niestety nie ma go na przykład Adobe SVG Viewer w wersji 3.0. Jedyną przeglądarką SVG, w której udało się uzyskać automatyczne odświeżanie parametrówi, jest przeglądarka Batik, tworzona przez Apache Foundation, w wersji 1.5 (więcej informacji o przeglądarkach w rozdz. 3.8).

Teoretycznie, według specyfikacji SVG, nie byłoby konieczne usuwanie i ponowne dodawanie elementu <use/>. Powinna wystarczyć sama zmiana atrybutu xlink:href. Niestety takiej funkcjonalności nie udało mi się uzyskać w żadnej z dostępnych przeglądarek.

Szablony realizujące dynamiczne odświeżanie parametru, a więc generujące część definicyjną schematu oraz część z pozostałymi elementami i skryptami, były więc pisane w myślą o przeglądarce Batik. Jedną z cech Batika jest przechowywanie ściągniętych dokumentów w lokalnym schowku, co zmusza do sztucznej zmiany dowiązań do dokumentów z definicjami. Zmiana ta polega na dołączaniu do dowiązania ignorowanej przez serwer części zawierającej licznik odwołań. Zaletą takiego zachowania jest natomiast to, że każdy dokument z definicjami jest ściągany tylko raz, ponieważ w danym momencie wszystkie odwołania do parametrów używają tej samej wartości licznika. Po kolejnych 10 sekundach skrypty zwiększą licznik o 1 i znów dokument z definicjami zostanie ściągnięty tylko raz, przy pierwszej modyfikacji odnoszącego się do niego elementu. Kolejne odwołania będą korzystały z wartości w schowku.

Statyczny i dynamiczny SVG nie wyczerpują wszystkich wymagań dotyczących prezentacji danych. Duża klasa użytkowników (przynajmniej tych oglądających schematy okazjonalnie) nie będzie dysponowała przeglądarką obsługującą SVG. Konieczna jest więc także możliwość prezentowania schematu w postaci bitmapy. Oczywiście samo generowanie bitmapy nie jest zadaniem procesora XSLT, ale jakiegoś programu renderującego SVG, natomiast przydatna byłaby integracja tego programu z będącym częścią procesora dokumentów serwerem HTTP.

Aby generowanej bitmapie stworzyć odpowiednie otoczenie (a więc np. możliwość umieszczenia dowiązań), jest ona zagłębiana w dokumencie HTML. Dokument ten generowany jest przez procesor XSLT z pliku źródłowego, zawierającego uproszczony dokument HTML. Do dokumentu tego procesor dodaje nagłówek z tytułem i pasek nawigacyjny. Pozwala to na automatyczne nadawanie dokumentowi odpowiedniego wyglądu i rozdzielenie formatowania dokumentu i jego treści. Poza innymi elementami HTML dokument ten może zawierać element <isl:schema/>, powodujący wstawienie do dokumentu HTML schematu określonego przez atrybut src9.

Dodatkową zaletą takiego rozwiązania jest możliwość generowania dokumentu, który będzie poprawnie wyświetlany zarówno w przeglądarkach obsługujących SVG, jak i nie posiadających tej funkcji. W ogólnym przypadku stwierdzenie, czy przeglądarka potrafi wyświetlać SVG, nie jest łatwe. Wymaga to m.in. odpytywania przeglądarki o obsługiwane wtyczki, np. za pomocą skryptów. Będzie się to odbywało inaczej w każdym modelu przeglądarki.

Tymczasem procesor XSLT generuje na miejsce elementu <isl:schema/> element <object/>. Zgodnie ze specyfikacją HTML 4.01 [16], zawiera on dowiązanie do obiektu (w tym wypadku dokumentu SVG) wraz z opisem jego typu. Jeżeli przeglądarka nie obsługuje obiektów danego typu, to powinna rozpocząć parsowanie zawartości elementu <object/>. Jako zawartość przygotowany przeze mnie szablon wstawia odnośnik do obrazka, będącego bitmapową reprezentacją schematu. Obrazek dodatkowo jest wyposażony w mapę (element <map/> HTML), co pozwala na emulowanie zachowania dowiązań występujących na oryginalnym schemacie. Dowiązania są umieszczane na mapie tylko wtedy, gdy mają dodany przez autora schematu atrybut określający ich położenie na obrazku w punktach (zobacz p. 3.6.1). Jeżeli atrybutu brak, to dowiązanie jest dołączane nad obrazkiem w postaci tekstowej.

W rezultacie, jeśli przeglądarka obsługuje SVG,to użytkownik otrzymuje stronę HTML z zagłębionym statycznym obrazkiem SVG (z ewentualnymi dowiązaniami). Jeżeli nie, to użytkownik widzi obrazek rastrowy. Jeżeli autor schematu o to zabrał, to dowiązania są dostępne bezpośrednio z obrazka, podobnie jak w SVG. Lista dowiązań bez odpowiednich atrybutów określających ich położenie na obrazku jest dostępna powyżej obrazka w postaci tekstowej.

Przewaga SVG na bitmapą polega nie tylko na możliwości dowolnego powiększania wybranego fragmentu obrazu, przesuwania go i lepszej obsłudze dowiązań, ale także na zwykle mniejszych rozmiarach obrazków. Przeciętnie schemat w postaci SVG spakowany algorytmem LZ77 [5] (używanym przez popularny program GNU zip i obsługiwanym przez większość przeglądarek) ma rozmiar około 10 razy mniejszy niż odpowiadająca mu grafika w formacie PNG. Poza tym oczywiście tylko użycie SVG umożliwia automatyczne odświeżanie wartości parametrów.

 
Poza przetwarzaniem dokumentów przez procesor XSLT, generowaniem grafiki bitmapowej z dokumentów SVG oraz udostępnianiem tych dokumentów przez serwer HTTP, procesor dokumentów powinien zapewnić wygodne środowisko pozwalające na budowanie struktury serwisu WWW. Serwis taki może składać się z wielu połączonych ze sobą dowiązaniami schematów i innych dokumentów -- wspomnianych dokumentów HTML/ISL, innych dokumentów HTML, elementów grafiki do budowania stron oraz plików konfiguracyjnych określających wzajemne powiązania dokumentów i sposób ich przetwarzania przez procesor XSLT. W szczególności chcielibyśmy mieć możliwość dowolnego dodawania i modyfikowania szablonów XSLT.

W podrozdziałach 3.7.23.7.3 opisuję dwie wykonane implementacje procesora dokumentów, pierwszą z wykorzystaniem istniejącego oprogramowania, a drugą napisaną od podstaw przeze mnie. Dodatek C zawiera wykorzystywane w systemie szablony XSLT.

3.7.2   Implementacja z wykorzystaniem serwera Apache Cocoon

Początkowo zakładałem samodzielną implementację procesora dokumentów, realizującego funkcjonalność opisaną w p. 3.7.1. Natknąłem się jednak na gotowe oprogramowanie, wykonujące zadania, jakie postawiłem przed procesorem dokumentów. Oprogramowaniem tym jest Cocoon, tworzony w ramach projektu Apache.

Autorzy określają Cocoona jako XML publishing framework [9], co można by przetłumaczyć jako zestaw narzędzi do publikowania dokumentów XML. Projekt został rozpoczęty w 1999 roku, obecnie dostępna jest wersja 2 Cocoona.

Cocoon jest bardzo złożonym systemem, zapewniającym komplet narzędzi i usług do budowania serwisów WWW opartych na technologii XML. Pozwala na eleganckie rozdzielenie logiki serwisu, jego zawartości, wyglądu i samego zarządzania serwisem. Podstawową technologią jest XSLT, ale Cocoon potrafi dużo więcej.

Cocoon jest napisany w Javie i zazwyczaj używany się go jako aplikacji kontenera serwletów (ang. servlet container), np. Tomcata [10], także tworzonego w ramach projektu Apache.

Żądanie przekazane np. przez Tomcata do Cocoona jest przetwarzane w dynamicznym potoku (ang. pipeline). Sposób przetwarzania żądania może zależeć od typu przeglądarki, podanego adresu i przekazanych opcji. Czytane podczas przetwarzania potoku dokumenty źródłowe XML przechodzą przez szereg faz przetwarzania. W najprostszym przypadku mogą być odczytane z dysku i wysłane do klienta. W bardziej skomplikowanym, po drodze przechodzą szereg przekształceń, dokonywanych między innymi przez procesor XSLT, a na końcu mogą zostać przekształcone przez obiekt serializujący (czyli produkujący postać końcową, niekoniecznie będącą dokumentem XML, ale np. obrazkiem). W czasie przetwarzania żądania mogą być wykonywane odpowiednio zdefiniowane akcje (np. aktualizacja informacji w bazie danych).

Cocoon w pełni wykorzystuje możliwości dynamicznego ładowania kodu, oferowane przez Javę. Oferuje łatwą integrację z JSP (Java Server Pages) i komunikację z bazami danych.

Plik konfiguracyjny opisuje drogę, jaką przebywają generowane dokumenty. Na początku zawiera deklaracje używanych elementów. Są wśród nich obiekty służące do odczytywania danych z dysku, pobierania z sieci i bazy danych, transformacji dokumentów z użyciem XSLT, XInclusions10 i innych, generowania danych binarnych, obsługi błędów i wykonywania wielu innych akcji. Deklaracja każdego z elementów zawiera, poza różnego rodzaju opcjami, także ścieżkę dostępu do skompilowanej klasy Javy realizującej funkcjonalność elementu. Pozwala to na proste wykorzystanie nie tylko bogatego zestawu gotowych elementów, ale także dołączanie własnych klas.

Najważniejszą częścią konfiguracji są opisy potoków, w jakich przetwarzane są dokumenty. Na początku opisu znajdują się warunki, jakie musi spełniać żądanie, aby trafić do danego potoku (najczęściej jest to odpowiednia postać URI). Następnie opisany jest przebieg przetwarzania dokumentu przez zdefiniowane wcześniej elementy.

W miarę możliwości wszystkie używane elementy trzymane są w postaci skompilowanego kodu Javy, co zwiększa szybkość ich przetwarzania. Poza tym Cocoon zawiera zaawansowany system zarządzania buforowaniem dokumentów.

Szczególnie atrakcyjną z mojego punktu widzenia cechą Cocoona jest wbudowana obsługa SVG. Standardowo w systemie dostępny jest obiekt serializujący SVG, czyli przekształcający dokument SVG w grafikę w jednym z powszechnie używanych formatów, np. PNG. Używa on wspominanego już pakietu Batik, zapewniającego renderowanie wszystkich wymienionych przez specyfikację elementów SVG.

Oczywiście do moich potrzeb wystarczało wykorzystanie tylko niewielkiej części możliwości Cocoona, zwłaszcza że generowałem stosunkowo niewielką liczbę dokumentów, wykorzystując właściwie tylko procesor XSLT.

Ponieważ z tych samych źródeł (schematów w SVG/ISL) miałem generować różne rodzaje dokumentów wyjściowych, zdecydowałem się na rozróżnianie ich przez prefiks dodawany do ścieżki dostępu do zasobu. Ma to tę przewagę nad wykorzystaniem rozszerzeń plików, że ułatwia tworzenie dowiązań względnych. Gdybym wykorzystywał rozszerzenia, musiałbym modyfikować dowiązania wewnątrz dokumentów, tak aby to samo dowiązanie w dokumencie schemat1.svg wskazywało na schemat2.svg, a w dokumencie schemat1.html na schemat2.html. Tymczasem jeżeli mam dokument o ścieżce dostępu svg/schemat1.isl, to mogę w nim umieścić link do dokumentu svg/schemat2.isl po prostu przez podanie nazwy schemat2.isl. Ten samo dowiązanie będzie poprawne w dokumencie HTML, wskazując na dokument html/schemat2.isl.

Musiałem przyjąć jakąś ogólną strukturę układu dokumentów źródłowych, wspólną dla wszystkich potencjalnych instalacji, co pozwoliłoby na utworzenie uniwersalnego pliku konfiguracyjnego. Chciałem także, aby struktura pozwoliła na trzymanie na jednym fizycznym serwerze konfiguracji dla wielu obiektów, czyli konkretnych instalacji systemu wizualizacji. Struktura ta ostatecznie wygląda następująco:

 
Użytkownik odwołuje się do dokumentów przez podanie ścieżki dostępu w postaci:  
http://adres_serwera/nazwa_obiektu/rodzaj_dokumentu/nazwa_dokumentu  
Nazwa obiektu jest tożsama z nazwą katalogu, domyślnie jest to main. Rodzaj dokumentu może być jednym z: Możliwych jest jeszcze kilka innych wartości, koniecznych np. do obsługi dokumentów z definicjami przy automatycznym odświeżaniu parametrów (zobacz p. 3.7.1). Nie będą one jednak raczej wpisywane przez użytkowników w przeglądarce. Domyślnie generowane są dokumenty HTML. Jedynie w przypadku przeglądarki Batik użytkownik będzie musiał dodać prefiks svg lub dsvg, aby przeglądać bezpośrednio dokumenty SVG, gdyż Batik nie obsługuje HTML (zobacz 3.8). Dodatek A.2 zawiera cały plik konfiguracyjny opisujący strukturę serwisu. Struktura pliku menu.xml jest opisana w dodatku A.3.

Przyjęte rozwiązania pozwalają na bardzo łatwe rozbudowywanie i modyfikację serwisu. Dodanie nowego obiektu (zestawu schematów) wiąże się z utworzeniem nowego katalogu. Nowe schematy wystarczy skopiować do odpowiedniego dokumentu i ewentualnie dodać wpis do pliku menu.xml. Nie wymaga to żadnych zmian w plikach konfiguracyjnych.

Pod względem instalacji i konfiguracji procesor dokumentów korzystający z serwera Apache Cocoon jest zupełnie niezależny od pozostałych części systemu wizualizacji. Ze względu na wykorzystanie Javy może być także uruchamiany na komputerze z innym niż Linux systemem operacyjnym. Dodatkowo, duże możliwości Cocoona pozwalają na budowę na jego podstawie bardziej skomplikowanego serwisu WWW dla obsługiwanego obiektu przemysłowego i ewentualną jego integrację z systemem wizualizacji.

 
Próbna wersja systemu z Cocoonem działała przez kilka tygodni na serwerze firmy Praterm w Warszawie. Niestety, ta testowa instalacja wykazała, że rozwiązanie to nie spełnia części postawionych wymagań.

Autorzy Cocoona twierdzą, że został on napisany z dużą dbałością o wydajność i zużycie pamięci, między innymi przez przekompilowywanie używanych dokumentów oraz używanie parserów XML typu SAX, nie wymagających wczytywania do pamięci całego dokumentu. Ma to zapewnić możliwość przetwarzania jednocześnie wielu olbrzymich dokumentów przy niewielkim zużyciu pamięci [9].

Niestety wnioski z instalacji testowej są zgoła odmienne. Pierwszą sprawą rzucającą się w oczy jest olbrzymie zapotrzebowanie na pamięć. W systemie z zainstalowaną pamięcią operacyjną o wielkości 256 MB, oraz partycją wymiany (ang. swap) o wielkości 500 MB, działanie Cocoona powodowało nie tylko olbrzymie spowolnienie pracy systemu przez intensywne korzystanie z partycji wymiany, ale także zgłaszanie przez maszynę wirtualną Javy komunikatów o braku pamięci.

Stabilność działania całości także nie jest najlepsza. Cocoon potrzebuje sporo czasu po uruchomiwniu, żeby zacząć poprawnie działać. W czasie pierwszym kilku odwołań po starcie zdarzają się dziwne błędy, typu nieprzekazywanie parametrów do procesora XSLT. W czasie późniejszej pracy także zdarza mu się czasami odesłać przeglądarce pusty dokument, co zapewne w większości przypadków wiąże się z kłopotami z pamięcią.

Do działania konwersji SVG do grafiki bitmapowej w systemach typu UNIX potrzebny jest działający X serwer (wykorzystują go klasy Javy używane przez Batika do tworzenia grafiki11). Jest to problemem, jeżeli chcemy, aby Cocoon był uruchamiany automatycznie przy starcie, między innymi ze względu na problemy z autoryzacją Batika wobec X serwera. Może to wymagać modyfikacji skryptów startowych systemu.

Sama instalacja Cocoona nie jest prosta. Wymaga zainstalowania wcześniej maszyny wirtualnej Javy oraz Tomcata. Nie wszystkie kombinacje wersji trzech wymaganych elementów chcą ze sobą poprawnie współpracować (między innymi używana przeze mnie wersja Cocoona 2.0.1 nie chciała działać z Javą w wersji 1.4 oraz Tomcatem nowszym niż 4.0.1). Obie wykonane przeze mnie instalacje, na dwóch różnych komputerach z systemem GNU/Linux, wymagały ręcznych ingerencji, wykraczających poza kroki opisane w dokumentacji serwera.

Część z tych problemów wynika prawdopodobnie z nienajlepszego opracowania linuksowych wersji maszyny wirtualnej Javy (które są np. przez firmę Sun traktowane nieco po macoszemu w stosunku do wersji przeznaczonych dla systemów Windows). Problem z pamięcią można by prawdopodobnie rozwiązać przez dokupienie większej ilości pamięci, oraz, być może, użycie innych wersji elementów systemu. Ogólnie nie wystawia to jednak najlepszego świadectwa dojrzałości Javy jako narzędzia do tworzenia dużych i skomplikowanych systemów.

O ile praca wykonana przy dostrajaniu systemu mogłaby być do zaakceptowania w przypadku pojedynczej instalacji, to staje się poważnym kłopotem jeśli chcemy wykonać ich więcej. Zgodnie z wymaganiami opisanymi w p. 2.10, dotyczącymi instalacji systemu na istniejącym sprzęcie, być może nienajwyższej klasy, wymagania pamięciowe Cocoona także wydają się trudne do zaakceptowania.

W tej sytuacji, po zebraniu doświadczeń z dwoma wykonanymi instalacjami systemu wizualizacji z serwerem Cocoon, podjąłem decyzję o implementacji własnego rozwiązania. Powinno one mieć, być może kosztem mniejszej funkcjonalności, nieduże wymagania sprzętowe i charakteryzować się prostotą instalacji. Własną implementację procesora dokumentów opisuję w p. 3.7.3. To właśnie rozwiązanie było podstawą do wykonanego w ramach pracy wdrożenia.

Możliwość wykorzystania Cocoona nadal pozostaje otwarta. Może być on użyty jako część systemu wizualizacji tam, gdzie większe wymagania wobec funkcjonalności oraz opisane niedostatki drugiego proponowanego rozwiązania, uzasadniają większe nakłady na sprzęt, instalację i konfigurację systemu.

3.7.3   Implementacja własnego procesora dokumentów opartego na XSLT

Przystępując do samodzielnej implementacji procesora dokumentów miałem bardzo dokładnie określony obraz tego, co chciałem uzyskać. Zaproponowana przez Cocoon struktura konfiguracji i ustalony przeze mnie schemat tworzenia serwisu okazał się wygodny i dobrze spełniający wymagania dotyczące łatwości modyfikowania i dodawania nowych schematów. Także przygotowane przeze mnie szablony XSL zakładały w pewien sposób konkretny układ dokumentów źródłowych, między innymi przy obsłudze dowiązań względnych.

Zdecydowałem więc, że mój program będzie musiał emulować wykorzystywaną przeze mnie część funkcjonalności Cocoon, korzystając z takiego samego schematu rozmieszczenia dokumentów źródłowych i tych samych szablonów. Pozwala to także na swobodną podmianę używanego procesora dokumentów z mojego rozwiązania na serwer Cocoon i odwrotnie.

Rozważałem także możliwość wykorzystania bezpośrednio plików konfiguracyjnych Cocoona sitemap.xmap, ale odrzuciłem ostatecznie to rozwiązanie. Pliki te są dość rozbudowane i dotyczą także funkcjonalności, której nie miałem zamiaru implementować. W szczególności istotną ich częścią są ścieżki do skompilowanych klas Javy, które w moim rozwiązaniu nie mogłyby być obsługiwane w żaden rozsądny sposób. Poza tym pojawiła się także potrzeba dodania rozszerzeń, specyficznych dla mojego programu, a związanych np. z obsługą schowka, który w Cocoonie jest obsługiwany na nieco innym poziomie (w plikach konfiguracyjnych cocoon.xconf).

Ponieważ głównym powodem pisania programu były wymagania wydajnościowe, naturalnym wyborem języka programowania było C. Podobnie jak w wypadku serwera parametrów, ze względu na łatwiejszą modyfikację programów obiektowych ostatecznie jest to proste C++. Umożliwiło to także wykorzystanie napisanej wcześniej biblioteki do realizacji funkcjonalności serwera HTTP (opis biblioteki znajduje się w p. 3.4).

Oferowaną przez program funkcjonalność można najłatwiej opisać przez prześledzenie struktury pliku konfiguracyjnego programu. Ścieżka do tego pliku jest zapisana w głównym pliku konfiguracyjnym systemu SZARP.

Struktura pliku konfiguracyjnego inspirowana jest rozwiązaniami zastosowanymi w Cocoonie. Oparta jest na potokach opisujących sposób przetwarzania żądań klienta i ma postać dokumentu XML. Decyzja o wyborze konkretnego potoku oparta jest na związanym z nim wyrażeniu regularnym, do którego dopasowywana jest podana przez klienta ścieżka (URI). Po podjęciu decyzji o wyborze potoku, zależnie od jego postaci, może być wykonanych kilka różnych akcji: Formalny opis formatu pliku konfiguracyjnego programu jest zawarty w dodatku A.4. Wszelkie informacje o błędach w konfiguracji zapisywane są w dziennikach programu.

Struktura samego programu jest dość prosta. Podczas wczytywania pliku konfiguracyjnego tworzone są obiekty odpowiednich klas Macher, TransformerSerializer, odpowiadające elementom <match/>, <transform/><serializer/> z pliku konfiguracyjnego. Do parsowania dokumentów XML oraz jako biblioteka kliencka HTTP (do pobierania dokumentów źródłowych z sieci) wykorzystywana jest biblioteka libxml2 [12]. Do transformacji XSLT używam biblioteki libxslt [13]. Aby przyspieszyć przetwarzanie dokumentów, szablony XSLT wczytywane są raz, przy pierwszym odwołaniu i przechowywane w postaci prekompilowanej. Żądania klientów parsowane są przez bibliotekę HTTP i przekazywane do obiektu, który wybiera odpowiedni pasujący potok i zleca mu przetworzenie dokumentu. Wygenerowany dokument lub informacja o przekierowaniu zwracane są do biblioteki HTTP, która wysyła odpowiedź do klienta.

Źródłowe dokumenty XML wczytywane są do pamięci i tam przetrzymywane oraz przetwarzane. Skutkuje to dość szybką pracą programu, ale powoduje ograniczenie wielkości przetwarzanych dokumentów przez dostępną pamięci operacyjną. W zastosowaniu programu jako części systemu wizualizacji nie powinno to być problemem, gdyż przetwarzane dokumenty nie są bardzo duże, może to mieć natomiast znaczenie przy ewentualnych innych zastosowaniach.

 
Jednym z większych problemów, jakie napotkałem w trakcie pisania programu, była realizacja rasteryzacji SVG. Samodzielne jej napisanie przekracza znacznie objętość pracy magisterskiej. Okazało się także, że nie ma dostępnych żadnych darmowych bibliotek w języku C. Istnieją właściwie tylko dwie biblioteki, Batik oraz SVGToolkit, obie napisane w Javie. Ze względu na problemy opisane w rozdziale o Cocoonie (3.7.2), nie chciałem jednak korzystać z rozwiązań w Javie.

Ostatecznie udało mi się napisać funkcję eksportującą dokument SVG do formatu PNG z wykorzystaniem kodu używanego przeze mnie edytora Sodipodi (zob. p. 3.6.2). Niestety rozwiązanie to ma szereg wad:

Wady te nie dyskwalifikują rozwiązania. Być może jednak, jeśli okażą się bardzo uciążliwe dla użytkowników, konieczne będzie inne rozwiązanie problemu rasteryzacji SVG, na przykład z wykorzystaniem jednak któregoś z rozwiązań wykorzystujących Javę.

Konieczność instalacji programu Sodipng komplikuje nieco instalację całego systemu. Na szczęście, poszczególne elementy systemu są od siebie niezależne. W szczególności procesor dokumentów będzie działał bez programu Sodipng, niedostępne będzie jedynie generowanie zastępczej postaci schematów -- grafiki w formacie PNG.

Instalacja i konfiguracja procesora dokumentów, zgodnie z wymaganiami, nie wymaga zmian w konfiguracji pozostałych elementów systemu. Konieczne jest jedynie dodanie parametru map_file do głównego pliku konfiguracyjnego systemu SZARP. Parametr ten wskazuje położenie pliku konfiguracyjnego programu.

Średni czas przetwarzania żądania klienta na komputerze z zegarem około 1 GHz wynosił podczas testów od poniżej 1 milisekundy (dla czytanych z dysku małych dokumentów), do kilku milisekund dla prostych generowanych dokumentów HTML. Generowanie bardziej skompilowanych schematów zajmowało do około 200 ms (dla schematów takich jak ten na stronie ??). Jedynie generowanie grafiki PNG za pomocą programu Sodipng jest dość wolne, dla prezentowanego schematu czas wynosił od pół do półtorej sekundy. Podane czasy nie uwzględniają czasu potrzebnego na przesłanie dokumentu przez sieć.

Zastosowania programu, nazwanego przeze mnie xsltd, nie ograniczają się tylko do tworzonego w ramach pracy systemu wizualizacji. Może on także służyć do budowania innego typu serwisów WWW, wymagających przetwarzania dokumentów XML za pomocą szablonów XSLT. Zaadoptowany z Cocoona schemat konfiguracji jest bardzo elastyczny, umożliwia dobre oddzielenie struktury logicznej serwisu (opisanej w pliku konfiguracyjnym) od zawartości dokumentów (zapisanej w samych dokumentach) i ich wyglądu (opisanych przez szablony XSLT). Dodawanie i modyfikacja dokumentów nie wymagają restartowania programu. Jedynie zmiany w szablonach zostaną uwzględnione dopiero przy ponownym uruchomieniu programu. Niewielkie w porównaniu z Cocoonem możliwości programu w części zastosowań są w pełni rekompensowane przez łatwość instalacji, szybkość działania i nieduże wymagania pamięciowe.

3.8   Oprogramowanie klienckie

Zgodnie z założeniami przedstawionymi w p. 3.1 oprogramowaniem klienckim dla tworzonego systemu mają być standardowe przeglądarki WWW. Wykorzystanie pełnych możliwości systemu wymaga jednak użycia przeglądarki obsługującej SVG.

SVG jest technologią stosunkowo młodą. Przyjemność z pracy z nowymi technologiami jest niestety często okupowana problemami, jakie towarzyszą ,,wiekowi młodzieńczemu'' tych rozwiązań. Specyfikacja SVG wydaje się dobrze skonstruowana. Wielu specjalistów uważa, że jest to jedna z  najważniejszych opracowanych ostatnio technologii dotyczących Internetu, która może poważnie wpłynąć na sposób korzystania z sieci, uwalniając użytkowników od nadal tekstowego w swojej istocie świata HTML12.

Ze względu na złożoność specyfikacji największym problemem nadal jest niewystarczająca liczba implementacji, zwłaszcza tych obsługujących pełny zakres funkcjonalności opisanej w specyfikacji, na przykład modyfikację dokumentu przez manipulowanie jego modelem obiektowym (ang. Document Object Model).

W moim projekcie przewidziałem zastosowanie 3 typów rozwiązań po stronie klienta, odpowiadających różnym poziomom obsługi SVG: Ponieważ zaimplementowane w ramach projektu rozwiązania, także te realizujące automatyczne odświeżanie parametrów, są zgodne z oficjalnymi specyfikacjami standardów W3C, jest nadzieja, że system będzie odnosił bezpośrednie korzyści z rozwoju dostępnych implementacji SVG. Pojawienie się przeglądarek wykorzystujących pełnię możliwości oferowanych przez SVG i inne pokrewne technologie jest zapewne tylko kwestią czasu. Być może więc opisane w tym rozdziale problemy techniczne, które miały dość spory wpływ na kształt implementacji projektu, za kilka lat będą mogły być traktowane wyłącznie jako historyczne ciekawostki.


1
Portable Network Graphics -- format skompresowanej grafiki bitmapowej używanej powszechnie w Internecie [3].
2
Document Object Model -- niezależny od platformy i języka programowania interfejs, pozwalający programom i skryptom na dostęp i modyfikację treści i struktury dokumentu XML.
3
Do obsługi XML wykorzystywana jest biblioteka libxml2, dostępna pod adresem http://www.xmlsoft.org [12].
4
Uniform Resource Identifier -- identyfikator określający położenie zasobu w sieci WWW, jego postać określa dokument RFC 2396.
5
Przykład ten można obejrzeć pod adresem http://www.praterm.com.pl:8180/test/termometr.html. Wyświetlana jest temperatura powietrza w Pasłęku.
6
Schemat dostępny jest też pod adresem http://213.76.238.20:8083.
7
Oficjalna strona projektu Sodipodi to http://sodipodi.sourceforge.net. Repozytorium CVS znajduje się na serwerze anoncvs.gnome.org, moduł sodipodi. Wpis w pliku ChangeLog dotyczący moich zmian znajduje się pod datą 4 maja 2002 roku.
8
Identyfikator przestrzeni nazw xlink musi być związany z URI http://www.w3.org/1999/xlink oznaczającą przestrzeń nazw XLink.
9
Dokumenty takie będę dalej nazywał dokumentami HTML/ISL. Dokładna specyfikacja ich formatu jest podana w dodatku B.3.
10
XML Include -- rekomendacja World Wide Web Consortium, określająca sposób tekstowego włączania dokumentów XML do innych dokumentów XML.
11
Wymaganie to nie występuje, jeśli korzystamy z Javy w wersji 1.4. Nie jest ona jednak do końca zgodna z poprzednimi wersjami, może wymagać przekompilowania programów.
12
Wybór najważniejszych artykułów, informacje o powstajacych implementacjach i inne ciekawostki dotyczące SVG można znaleźć na stronach World Wide Web Consortium, http://www.w3c.org.
13
Używany w formacie GIF algorytm kompresji LZW (Lempel-Ziv-Welsh) jest opatentowany przez UniSys. Dlatego też oprogramowanie tworzące grafikę w formacie GIF podlega opłacie patentowej na rzecz właściciela patentu. Patent obejmuje tylko oprogramowanie, które dokonuje zarówno kompresji jak i dekompresji, teoretycznie więc oprogramowanie tylko dekompresujące nie jest nim objęte. UniSys w przeszłości nie zgadzał się z taką interpretacją zapisów we wniosku patentowym. Informacje na podstawie: Graphics File Format FAQ: General Graphics Format Questions, http://www.ora.com/infocenters/gff/gff-faq/.

Previous Contents Next