Häiriöhavaintojärjestelmän Integraatio ...

87
Antti Heinonen Häiriöhavaintojärjestelmän Integraatio Liikenteenhallintajärjestelmään Tietotekniikan pro gradu -tutkielma 13. maaliskuuta 2019 Jyväskylän yliopisto Informaatioteknologian tiedekunta

Transcript of Häiriöhavaintojärjestelmän Integraatio ...

Antti Heinonen

Häiriöhavaintojärjestelmän Integraatio

Liikenteenhallintajärjestelmään

Tietotekniikan pro gradu -tutkielma

13. maaliskuuta 2019

Jyväskylän yliopisto

Informaatioteknologian tiedekunta

Tekijä: Antti Heinonen

Yhteystiedot: Antti Heinonen

Ohjaaja: Ville Isomöttönen

Työn nimi: Häiriöhavaintojärjestelmän Integraatio Liikenteenhallintajärjestelmään

Title in English: Integration of Disturbance Detection System Into Traffic Control Systems

Työ: Pro gradu -tutkielma

Suuntautumisvaihtoehto: Ohjelmistotekniikka

Sivumäärä: 87+0

Tiivistelmä: Tämä pro gradu keskittyy eritason komponenttien välisen kommunikaation

suunnittelemiseen ja toteutukseen. Tutkielma esittelee pääasialliset olevassaolemat toteutuk-

set Suomen liikennejärjestelmissä, niiden yhteisen arkkitehtuurin pääpiirteet sekä käsittelee

uuden laitetyypin integraatiota olemassaoleviin järjestelmiin.

Tutkielman lopputuloksena on uusi rajapinta liikenneviraston ohjelmistoihin, jonka avulla

pystytään välittämään ja vastaanottamaan viestejä koneoppimista hyödyntävälle kamerapoh-

jaiselle häiriöhavaintojärjestelmälle.

Avainsanat: gradu3, pro gradu -tutkielmat, Software Architecture, Software Design, C#,

WinCC OA, PLC

Abstract: This graduate thesis is focused on integration of components from different levels

of complexity and transmission of messages between these different systems. Thesis presents

the main architecture and existing solutions in Finnish traffic systems and focuses on creation

of a new integration layer of software and plc in order to effectively communicate between

REST-application and traffic cameras that detect disturbances using machine learning.

Keywords: gradu3, pro gradu -tutkielmat, Software Architecture, Software Design, C#,

WinCC OA, PLC

i

Esipuhe

Tämä Pro gradu tutkielma on toteutettu työsuhteen aikana YSP Oy -yrityksellä.

YSP Oy toimii konsulttina sekä liikenneteknisten järjestelmien toteuttajana Suomen Liiken-

nevirastolle. Pääasiallisena tuotteena toimii kokonaisratkaisujen tarjoaminen Liikenneviras-

tolle alkaen yksittäisten laitteiden tilaamisesta, asentamisesta ja logiikkaohjelmoinnista, jat-

kuen valvomo-ohjelmiston kautta REST-rajapintaan asti, johon Liikenneviraston Tieliiken-

teen ohjauksen integroitu käyttöliittymä (T-LOIK) ottaa yhteyden.

Jyväskylä, 13. maaliskuuta 2019

Antti Heinonen

ii

Termiluettelo

HTTP (lyhenne sanoista Hypertext Transfer Protocol) on protokolla,

jota selaimet ja palvelimet käyttävät viestiensä välitykseen.

TCP (lyhenne sanoista Transmission Control Protocol) on matalan

tason tietoliikenneprotokolla, jonka avulla tietokoneet viestivät

toisilleen.

REST (lyhenne sanoista Representational State Transfer) on HTTP-

protokollaan perustuva arkkitehtuurimalli ohjelmointirajapin-

tojen toteuttamiseen.

XML (engl. Extensible Markup Language) on XML-tyyppisten mer-

kintäkielien standardi, johon muunmuassa verkkosivujen HTML

kuuluu.

JSON (lyhenne sanoista JavaScript Object Notation) on avoimen stan-

dardin mukainen tiedostomuoto tiedonvälitykseen.

.NET Framework on Microsoftin kehittämä ohjelmistokomponenttikirjasto.

C# on Microsoftin kehittämä olio-ohjelmointikieli, joka pohjautuu

.Net-kirjastoon.

ASP.NET on avoimen lähdekoodin ohjelmistokehys modernien web-sovellusten

rakentamiseen.

AKKA.Net on työkalupaketti ajonaikaisten tapahtumapohjaisten ohjelmis-

tojen kehitykseen, joka pohjautuu .Net -kirjastoon.

NUnit on avoimen lähdekoodin kirjasto .NET-sovelluksien yksikkö-

testaamiseen.

SCADA (engl. Supervisory Control and Data Acquisition) on tietoko-

neohjelma, joka tarjoaa pohja-arkkitehtuurin erilaisiin automaa-

tiojärjestelmiin ja niiden hallintaan.

WinCC OA (engl. WinCC Open Architecture) on Siemensin kehittämä SCADA-

ohjelmistotuote.

PLC (engl. Programmable logic controller) on riisuttu tietokone, jo-

ta käytetään tosiaikasten automaatioprosessien ohjaamisessa.

iii

T-LOIK (lyhenne sanoista Tieliikenteen ohjauksen integroitu käyttöliit-

tymä) on järjestelmä, jonka tarkoituksena on vastaanottaa da-

taa ja hallita eri osia Suomen liikenteenhallintajärjestelmistä.

T-LOIK-Ohjaussovitin on järjestelmä, jonka tarkoituksena on toimia viestinvälittäjä-

nä SCADA-ohjelmiston ja/tai PLC-laitteiden sekä T-LOIK:n

välillä.

DriverManager on C# :lla toteutettu ajurialusta, joka pohjautuu microftin MEF-

applikaatioihin (Managed Extensible Framework).

iv

KuviotKuvio 1. Järjestelmän yleisarkkitehtuuri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3Kuvio 2. Esimerkki LD:n syntaksista, lähde “Ladder Logic Examples” 2018-10-16. . . . . . . 7Kuvio 3. Modbus TCP esimerkki, lähde: “How do you program and parameterize

Modbus/TCP communication between S7-1500 CPUs and S7-1200 CPUs?” (2018-10-16). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

Kuvio 4. T-LOIK-ohjaussovittimen tietovuo-kaavio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22Kuvio 5. DriverManager WinCC OA:n projektimanagerin aliprosessina . . . . . . . . . . . . . . . . . . . 25Kuvio 6. XaidDriverin arkkitehtuuri. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37Kuvio 7. XaidDriverin sisäinen rakenne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

TaulukotTaulukko 1. Modbus TCP:n rakenne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

v

Sisältö1 JOHDANTO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

2 ARKKITEHTUURIN YLEISKUVA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

3 PLC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63.1 Structured Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83.2 Modbus Protokolla . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113.3 PLC käyttötapauksia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

4 SCADA. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144.1 WinCC Open Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154.2 Datan vastaanottaminen ja välitys WinCC OA:ssa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

5 REST-ARKKITEHTUURI & T-LOIK-OHJAUSSOVITIN . . . . . . . . . . . . . . . . . . . . . . . . . . . 175.1 REST-arkkitehtuuri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185.2 T-LOIK-Ohjaussovitin ja Akka.NET. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

6 MANAGED EXTENSIBILITY FRAMEWORK & DRIVERMANAGER . . . . . . . . . . 24

7 X-AID HÄIRIÖNHAVAINTOJÄRJESTELMÄ JA TESTIVETOINEN KEHITYS . 287.1 Kuvaus X-AID häiriönhavaintojärjestelmästä . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297.2 X-AID-simulaattori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307.3 Testivetoinen kehitys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

8 XAIDDRIVER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328.1 Oliosuunnittelu ja XaidDriver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368.2 XaidDriverin kehityksessä sovelletut suunnittelumallit . . . . . . . . . . . . . . . . . . . . . . . . . 458.3 Datan representaatiot WinCC OA:ssa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 548.4 XaidDriverin datan käsittely WinCC OA:ssa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

9 X-AID INTEGRAATION TESTAAMINEN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 649.1 XaidDriverin yksikkötestaus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 659.2 Integraatiotestaus XaidDriverin ja WinCC OA:n välillä . . . . . . . . . . . . . . . . . . . . . . . . 669.3 Kenttätestien huomioita ja tuloksia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

10 YHTEENVETO JA JATKOTOIMENPITEET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

LÄHTEET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

vi

1 Johdanto

Liikennevirasto aloitti vuonna 2013 hankkeen, jonka tarkoituksena oli yhtenäistää useita

erilaisia Suomessa olevia liikenteenohjausjärjestelmiä (“Uusi tieliikenteen ohjausjärjestel-

mä (T-LOIK) nopeuttaa tiedonkulkua tienkäyttäjille ja helpottaa liikennepäivystäjien työtä”

2016-03-04). Tämän seurauksena syntyi yksi yhteistävä järjestelmä: T-LOIK (Tieliikenteen

ohjauksen integroitu käyttöliittymä). Koska Suomessa on melko paljon liikenteenohjaus-

järjestelmiä, on kaikkien pääasiallisten järjestelmien yhdistäminen T-LOIK-järjestelmään

usean vuoden prosessi.

Tämän pro gradun keskipisteenä on Etelä-Suomeen suunnitteilla oleva tunnelijärjestelmä.

Tunnelin läpi kulkee moottoritie ja tunnelin alue sisältää lukuisia erilaisia PLC-laitteita (Pro-

grammable Logic Controller), joita ohjataan SCADA-järjestelmien (Supervisory Control and

Data Acquisition) ja T-LOIK:n kautta. Tätä yleisarkkitehtuuria havainnoillistava kuvio 1 esi-

tellään tarkemmin seuraavassa kappaleessa. Tämän tunnelin SCADA-järjestelmä on toteutet-

tu Siemensin WinCC OA -järjestelmän pohjalta.

Tunnelin teknisesti kiinnostavimpia kohteita ohjelmistokehityksen näkökulmasta on tunne-

liin tuleva häiriöhavaintojärjestelmä (HHJ, X-AID). Tämä järjestelmä prosessoi videoku-

vaa koneoppimista hyödyntäen, tunnistaen liikennehäiriöitä ja välittää niistä tietoa SCADA-

järjestelmälle ja takaisin. Näiden viestien sisältönä on esimerkiksi pysähtynyt ajoneuvo, hi-

das ajoneuvo ja väärään suuntaan ajava ajoneuvo. Häiriötilanteita varten tunnelin ohjaus-

järjestelmään on rakennettu erilaisia reaktioita liikennekäyttäjän varoittamiseen ja kaistojen

sulkemiseen. Käytännössä erilaiset hälytykset laukaisevat sekvenssejä PLC-laitteissa, jotka

sitten reagoivat tilanteesta riippuen korrektilla tavalla, kuten sulkemalla jonkin kaistan ja oh-

jaamalla liikenteen toiseen suuntaan.

Tämän pro gradun lopputuloksena on X-AID-palvelimen TCP-yhteyden (Transmission Cont-

rol Protocol) sisäistä protokollaa tulkkaava ajuri, joka kommunikoi X-AID kameroiden ko-

neoppimis-palvelimen kanssa ja välittää hälytyksiä WinCC OA -pohjaiseen tunnelijärjestel-

mään.

Tulkki toteutetaan ajuriksi C#-ohjelmointikielellä DriverManager-ohjelmistoon, mistä syys-

1

tä tämän ajurin nimeksi tuli XaidDriver. DriverManager on C#-ohjelmointikielellä toteutettu

geneerinen ajurialusta, joka käyttää WinCC OA:n C# rajapintaa. Tämän ajurialustan tarkoi-

tuksena on helpottaa WinCC OA:n sisäisen CTRL-skriptikielen jatkamista C#-ohjelmointi-

kielellä, sillä C# taipuu helpommin kompleksisempiin operaatioihin kuin CTRL. Ajurialusta

nopeuttaa ja yksinkertaistaa ulkoisten rajapintojen toteutusta WinCC OA-järjestelmään.

Tämän pro gradun aikana havainnoillistetaan miten olemassaolevia järjestelmiä integroidaan

toimivaksi kokonaisuudeksi sekä osoitetaan kuinka useita eri kokonaisuuksia yksittäinen mo-

derni automaatiojärjestelmä sisältää. Tarkoituksena on kaventaa kuilua ohjelmistotekniikan

ja automaatiosuunnittelun välillä sekä tarjota tietoa tavoista integroida automaatiojärjestelmä

korkean tason ohjelmointikielten ohjelmiin. Tutkielma esittää erilaisia kehitystapoja ja suun-

nittelumalleja luotettavan ohjelmiston kehitykseen ja havainnoillistaa käytännön esimerkeil-

le kuinka näitä malleja voi hyödyntää.

Tutkielmassa käydään läpi ensin olemassaoleva arkkitehtuuri ja avataan miten tutkielman

eri luvut liittyvät olemassaolevaan arkkitehtuuriin. Tarkoituksena on vastata seuraaviin ky-

symyksiin: mikä on PLC, mitä tarkoittaa SCADA-järjestelmä ja kuinka se kommunikoi kor-

keamman tason ohjelmointikielten ohjelmien kanssa, miten nämä järjestelmät kommunikoi-

vat keskenään ja miten näistä osista muodostuu valvomo-ohjelmisto (luvut 2 - 4). Ohessa

avataan miten tällainen tunnelivalvomojärjestelmä yhdistetään TLOIK-järjestelmään (luku

5). Tämän jälkeen siirrytään käsittelemään XaidDriverin kehitystä: minkälaisten teknolo-

gioiden päälle tämä ajuri on rakennettu (luku 6), millaisia ohjelmistokehityksen menetelmiä

voidaan soveltaa kehityksen yhteydessä, kuinka järjestelmän toimivuutta testataan, millaisia

suunnittelumalleja toteutuksessa hyödynnetään, millaista ohjelmistoarkkitehtuuria HHJ:n in-

tegraatiossa käytetään ja lopulta miten tämä järjestelmä testataan laadullisesti (luvut 7 - 9).

Lopuksi arvioidaan protokollatulkin toimivuutta, mitä puutteita löytyi alustavan testaamisen

ohessa, mitä mahdollisia jatkotoimenpiteitä järjestelmän kokonaistestaamisessa voi ilmetä ja

miten niihin voi reagoida kyseisen järjestelmän loppuun hiomiseksi sekä pohditaan yleisesti

pro gradun onnistumista (luku 10).

2

2 Arkkitehtuurin yleiskuva

Häiriöhavaintojärjestelmän integroimisen näkökulmasta on olennaista esitellä kehitykses-

sä hyödynnettävät teknologiat: olennaisimmat ovat T-LOIK, T-LOIK-ohjaussovitin, WinCC

OA-järjestelmä, PLC logiikka, DriverManager ja X-AID-palvelin.

Kuvio 1. Järjestelmän yleisarkkitehtuuri

Kuvio 1 havainnollistaa komponenttien rooleja ja niiden välisiä tiedonvälitystapoja. Jokai-

sella komponentilla tässä kuvassa on oma roolinsa. Kamerat välittävät videokuvaa koneoppi-

mispalvelimelle ja koneoppimispalvelin tunnistaa liikennehäiriöitä kuvavirrasta. XaidDriver,

joka on toteutettu ajuriksi DriverManagerin sisälle, tulkkaa näitä viestejä. DriverManager re-

kisteröityy WinCC OA:n aliprosessiksi. WinCC OA on SCADA-järjestelmä, eli se kommu-

nikoi PLC-laitteiston kanssa ja tarjoaa graafisen käyttöliittymän liikenteen hallitsemiseksi

sekä valvomiseksi tunnelissa.

3

PLC-laitteisto ohjaa alimman tason laitteistoa, eli esimerkiksi liikennepuomeja tai liiken-

nevaloja. T-LOIK-ohjaussovitin kommunikoi SCADA-järjestelmän kanssa sekä toteuttaa T-

LOIK-järjestelmän rajapinnan. T-LOIK ohjaa useita eri SCADA-järjestelmiä ja PLC-laitteistoja,

toimien keskistettynä graafisena käyttöliittymänä liikennekeskuksen päivystäjälle.

XaidDriverin toteutus on siis suunnittelututkimuksen näkökulmasta Hevnerin ja Chatterjeen

(2010) määrittelemä "wicked problem", eli kansankielisesti häijy ongelma. Tämänkaltaiset

ongelmat Hevner ja Chatterjee määrittelevät seuraavilla tavoilla:

1 . Epätasaiset vaatimukset ja rajoitteet

2 . Kompleksiset interaktiot ongelman eri osakomponenttien välillä

3 . Luontainen joustavuus, joka vaikuttaa sekä suunnitteluprosessin että tuotoksien

muutoksiin.

4 . Kriittinen riippuvuus ihmisten kognitiivisiin kykyihin luoda tehokkaita ratkaisuja

5 . Kriittinen riippuvuus ihmisten sosiaalisiin kykyihin, johtuen tiimityön tarpeesta

Lienee selvää, että tämän kokoisessa integraatioprojektissa jokainen näistä osioista täyt-

tyy: pelkästään YSP Oy:lla on useita eri ihmisiä toteuttamassa ratkaisuja ongelman eri osa-

alueisiin: ihmisiä suunnittelemassa IP-verkot sekä laitteiston välistä kommunikaatiota, ihmi-

siä tuottamassa logiikkakoodia ja asentamassa PLC-laitteistoa, CTRL-skriptikieltä ja valvo-

moa koodaavia ihmisiä, korkean tason ohjelmointikielten ratkaisuja tuottavia ihmisiä sekä

projektipääliköitä. Kun tähän lisää yhteistyövaatimukset muiden yritysten sekä asiakkaan

kanssa, on häijy ongelma syntynyt. Tässä suunnittelututkimuksessa pyritäänkin katsomaan

tämän ongelman ratkaisua kokonaisuuden kannalta ja selittämään, kuinka tämänkaltaisen

ongelman voi ratkaista.

Pro Gradun ymmärtämisen helpottamiseksi aloitetaan kokonaisuuden osien läpikäynti ma-

talimmalta tasolta siirtyen koko ajan korkeammalle abstraktiotasolle. Tämä tarkoittaa, että

ensin käsitellään PLC-laitteiston osuutta kokonaisuudessa, mistä siirrytään korkeammalle

abstraktiotasolle SCADA-järjestelmiin. SCADA-järjestelmien läpikäymisen jälkeen keski-

tytään REST-arkkitehtuuriin ja TLOIK-ohjaussovittimeen, sillä näiden kautta integroidaan

tämä SCADA-järjestelmä T-LOIK:n järjestelmään. Komponenttien käsittelyn lopuksi käy-

4

dään läpi Microsoftin MEF-applikaatiot ja DriverManager, sillä näiden pohjalta toteutetaan

XaidDriver. Lopulta siirrytään paneutumaan itse XaidDriverin suunnitteluun, toteutukseen

ja testaukseen.

5

3 PLC

PLC (engl. Programmable Logic Controller) on pieni ohjelmoitava tietokone. Ohjelmoita-

vat logiikat ovat alunperin kehittyneet korvaamaan traditionaaliset releet (Erickson 1996).

PLC:n kehitti General Motorsin automaattivaihteisto-osasto vuonna 1968 (Erickson 1996),

Nykyään PLC-laitteisto toimii sekä CERN-tutkimuslaitoksessa (Fernandez Adiego, Prieto

Barreiro ja Blanco Vinuela 2011) että liikennevaloissa. Näitä pieniä tietokoneita löytää kaik-

kialta, sillä ne ovat yleiskäyttöisiä, nopeita ja niihin voi ohjelmoida oman logiikkansa. Kuten

Erickson (1996) toteaa: "Ohjelmoitavat logiikat ovat automatisaation eturintamalla."

Vuosien aikana PLC:n käyttötapaukset ja erilaiset tarpeenmukaiset muunnokset ovat muut-

taneet maailmaa. PLC-ohjelmoinnin perustana käytetään logiikkalohkoja. Ohjelmoitavat lo-

giikkalohkot kehittivät David W. Page ja LuVerne R. Peterson vuonna 1985 (Page ja Peterson

1985).

Logiikkalohkojen tarkoituksena on toteuttaa boolean logiiikkaa ja ne toimivat logiikkaohjel-

moinnin ohjelmointiparadigman mukaisesti. Alunperin PLC-ohjelmoinnin tärkein osa olivat

LD:t (Ladder Diagram). Näiden diagrammien oli tarkoitus havainnoillistaa ohjelman raken-

netta sähkökaaviota muistuttavalla tavalla.

Kuviossa 2 esitetty esimerkki on varsin yksinkertainen, mutta oikean elämän sovelluksissa

vastaavia toiminnallisuuksia voi olla tuhansia. Myös ohjelmointi on työlästä: käytännössä

LD:a käyttäessä ohjelmoija joutuu kehitysympäristössään valitsemaan jonkin komponentin,

siirtämään sen haluamaansa paikkaan, valitsemaan toisen komponentin ja piirtämään näiden

välille kytkennän.

6

Kuvio 2. Esimerkki LD:n syntaksista, lähde “Ladder Logic Examples” 2018-10-16.

Jo tämän esimerkin perusteella voinee ymmärtää, että vastaavanlaiset ohjelmat paisuivat no-

peasti hyvin pitkiksi ja vaikealukuisiksi, mikä puolestaan teki PLC-ohjelmoinnista työläs-

tä. Ratkaisuna on kehittynyt useita eri kieliä, joita sovelletaan useimmiten tarpeen mukaan:

kieli on usein valmistajakohtainen. Esimerkiksi Schneider Electricsin laitteisto - jota YSP

pääasiassa käyttää - tukee Structured Text:iä.

Tässä pro gradussa keskitytään lähennä ST:iin, joka on määritelty PLCOpen IEC 61131-3

standardissa (Tiegelkamp ja John 1995). Nykyään tätä standardia seuraavia kieliä on viisi:

aiemmin mainittu LD ja ST, FBD (Function Block Diagram), IL (Instruction List, nykyään

deprekoitunut) sekä SFC (Sequential Function Chart). Näistä kielistä erityistä huomiota tässä

tutkielmassa saa ST, sillä tämän projektin PLC-laitteisto toimii sillä.

7

3.1 Structured Text

ST on tekstipohjainen verrattuna LD:n graafisuuteen. Sen ulkonäkö muistuttaa korkeamman

tason ohjelmointikieliä ja sen syntaksi on varsin helppolukuista. Tarkemmalla tarkastelulla

kuitenkin huomaa näiden ohjelmointikielten suuren eron, mistä syystä seuraavassa esimer-

kissä havainnoillistetaan liikennevalon keltaisen valon käyttäytymistä (YSP Oy, 2019).

(∗ Yellow f l a s h ∗ )

i f s e q S t e p =1 or s e q S t e p =6 or s e q S t e p =8 or s e q S t e p =10 then

d e v i c e O u t . c o n t r o l R e d L i g h t : = 0 ;

d e v i c e O u t . c o n t r o l G r e e n L i g h t : = 0 ;

i f s e q S t e p =1 then

yel lowFlashCTU (CU:= yellowFlashTON2 . Q, PV: = 0 ,R: = 0 ) ;

e n d _ i f ;

i f s c a d a S t a t u s . a l e r t C o m m u n i c a t i o n E r r o r =0 then

s c a d a S t a t u s . y e l l o w L i g h t F l a s h : = 1 ;

e l s e

s c a d a S t a t u s . y e l l o w L i g h t F l a s h : = 0 ;

e n d _ i f ;

ELSE

s c a d a S t a t u s . y e l l o w L i g h t F l a s h : = 0 ;

e n d _ i f ;

(∗ Yellow f l a s h t i m e r s ∗ )

yel lowFlashTON1 ( IN : = ( s c a d a S t a t u s . y e l l o w L i g h t F l a s h =1) and

n o t ( yel lowFlashTON2 .Q) , PT :=T#500ms ,Q =>

d e v i c e O u t . c o n t r o l Y e l l o w L i g h t ) ;

yellowFlashTON2 ( IN : = ( s c a d a S t a t u s . y e l l o w L i g h t F l a s h =1) and

yel lowFlashTON1 . Q, PT :=T#500ms ) ;

8

(∗ Yellow s o l i d ∗ )

i f s e q S t e p =2 then

d e v i c e O u t . c o n t r o l R e d L i g h t : = 0 ;

d e v i c e O u t . c o n t r o l Y e l l o w L i g h t : = 1 ;

d e v i c e O u t . c o n t r o l G r e e n L i g h t : = 0 ;

e n d _ i f ;

(∗ Red and y e l l ow ∗ )

i f s e q S t e p =4 then

d e v i c e O u t . c o n t r o l R e d L i g h t : = 1 ;

d e v i c e O u t . c o n t r o l Y e l l o w L i g h t : = 1 ;

d e v i c e O u t . c o n t r o l G r e e n L i g h t : = 0 ;

e n d _ i f ;

Jokaista eri valon väriä edustaa jokin numeerinen arvo, joka asetetaan status-arvoksi rekiste-

riin. Lienee myös syytä huomauttaa, että automaatiomaailmassa tilavaihtumien toteutuksessa

on aina sekä kontrolliarvo että statusarvo. Tämä johtuu siitä, että mahdollisten yhteysongel-

mien tai muiden käyttämiseen vaikuttavien tekijöiden yhteydessä näin pystyy vertaamaan

viimeksi annettua kontrolliarvoa ja varsinaista statusarvoa, varmistuen näin ohjauksen on-

nistumisesta. Kuten SCADA-luvussakin tullaan huomauttamaan, automaatiojärjestelmissä

luotettavuus on aina ensimmäinen prioriteetti.

Kieli sisältää mm. switch-case-lauseita, silmukoita, if-then-else -lauseita ja primitiivisiä funk-

tioita (sqrt(), sin()). Myös perustietotyypit ovat mukana: bitit, kokonaisluvut, reaaliluvut,

ajankesto, päivämäärä, ajankohta, päivämäärä ja ajankohta sekä tekstinpätkä. Myös muut-

tujat voivat olla paikallisia tai globaaleja, eli samankaltaisuuksia olio-ohjelmointiin löytyy.

PLC-ohjelmat toimivat ikuisessa silmukassa, jossa toteutetaan erilaisia sekvenssejä.

9

ST:n operaattorit sekä lausekkeet voi karkeasti jakaa neljään eri luokkaan (“Structured Text

Tutorial to Expand Your PLC Programming Skills” 2018-09-20):

1 . A r i t m e e t t i s e t o p e r a a t i o t

2 . R e l a a t i o n a a l i s e t o p e r a a t i o t

3 . L o o g i s e t o p e r a a t i o t

4 . B i t t i o p e r a a t i o t

Aritmeettiset operaatiot sisältävät summalaskut, negaatiot ja vähennyslaskut, moninkerrat,

eksponentit, jakamisen sekä modulon. Relaationaaliset operaatiot puolestaan sisältävät yh-

täkuin, pienempi kuin, pienempi tai yhtä iso kuin, suurempi kuin, suurempi tai yhtä iso

kuin ja ei samankokoiset vertailut. Loogiset operaatiot ja bittioperaatiot puolestaan sisäl-

tävät AND:in, OR:in, XOR:in ja NOT:in. Erona näiden käytössä bittioperaatioissa verrattu-

na loogisiin operaatioihin on, että samat toiminnot suoritetaan bittitasolla, eli boolean logii-

kan totuustaulujen mukaisesti (“Structured Text Tutorial to Expand Your PLC Programming

Skills” 2018-09-20).

ST:n suurin hyöty on koodin kierrätettävyys (“Structured Text Tutorial to Expand Your PLC

Programming Skills” 2018-09-20). LD:n graafisuuden sijasta tekstipohjainen ohjelmointi-

kieli on suuri etu, sillä samaa koodia pystyy tällä tavalla helposti uudellenkäyttämään. Tii-

vistettynä ST on siis tekstipohjainen vastaus LD:n graafiselle lähtökohdalle, minkä tuomat

edut ovat merkittäviä verrattuna graafiseen kieleen. PLC-laitteiden tarvitsee kuitenkin usein

kommunikoida toisten laitteiden kanssa. Tätä varten on kehitelty erilaisia tiedonsiirtoproto-

kollia, joista yksi on Modbus.

10

3.2 Modbus Protokolla

Yksinkertaisissa laitteissa ja käyttötapauksissa, esimerkiksi yksinkertaisessa palohälyttimes-

sä, riittää, että kolvaa kuparilangan kiinni virtapiiriin, jotta saa signaalin milloin kyseinen

laite hälyttää. Kompleksisemmissa tapauksissa sovelletaan jotakin tiedonvälitys-protokollaa.

Yksi käytettävistä protokollista on Modbus. Modbus on myös tämän tutkielman kannalta

olennainen, sillä projektin laitteisto käyttää Modbus-protokollaa.

Modbus on Modiconin (nykyään Schneider Electric) vuonna 1979 julkaisema sarjaliikenne-

protokolla. Nykyään se toimii teollisuuden de facto -standardina, eli suurin osa maailman

automaatiojärjestelmistä toimii Modbus-protokollalla (Phan 2012). Suuri osa nykyajan au-

tomaatioista itseasiassa käyttää jonkinlaista muunnelmaa virallisesta Modbus-protokollasta.

Yksittäinen laite käyttää Modbus-protokollaa, jonka avulla se saa ohjeistuksensa logiikkaoh-

jelmalta. Tämän jälkeen laite välittää viestinsä samalla protokollalla eteenpäin.

Jokainen modbus-yhteys koostuu ohjaaja-ohjattava (master-slave) -tyyppisestä kommuni-

kaatiosta. Tämä tarkoittaa että master-laite lähettää viestejä, joita slave-laite kuuntelee ja to-

teuttaa annetut käskyt. Modbus on sarjaliikenne protokolla, joka toimii parikaapelilla. Moni-

mutkaisemmissa tapauksissa laitteeseen liitetään Ethernet-portti tai sarjakytkentä, mitkä kon-

figuroidaan kommunikoimaan Modbus-protokollan kanssa, jolloin kyseiseen laitteeseen on

mahdollista päästä käsiksi TCP/IP-protokollilla (Modbus 2004). Tällöin puhutaan Modbus-

protokollan variaatiosta: Modbus TCP/IP - tai Modbus TCP -protokollasta. Muunneltu Mod-

bus TCP siis vie Modbus protokollan TCP:n sovelluskerrokseen. Lukuisista Modbus-variaatioista

huolimatta tässä tutkielmassa keskitytään lähinnä aiemmin mainittuun TCP/IP -variaatioon

Modbus-protokollasta, sillä se on tämän projektin laitetoiminnan ymmärtämisen kannalta

olennaisin variaatio kyseisestä protokollasta. Viestien välitys tapahtuu kirjoittamalla laittei-

den rekistereihin erilaisia arvoja, joita lukemalla tämä laitteisto saa käskynsä.

11

Kuvio 3. Modbus TCP esimerkki, lähde: “How do you program and parameterize Mod-

bus/TCP communication between S7-1500 CPUs and S7-1200 CPUs?” (2018-10-16).

Modbus TCP/IP -protokolla toimii hyvin samankaltaisella tavalla kuin perinteinen asiakas-

palvelin -arkkitehtuuri, jota enemmistö internetistä käyttää. Modbus-protokollan käyttämä

portti on 502. Modbus-viestin kehys koostuu sovelluksen data yksiköstä (ADU, Applica-

tion Data Unit), joka kapseloi sisällensä protokolla data yksikön (PDU, Protocol Data Unit).

ADU koostuu osoitteesta, PDU:sta ja virheentarkistuksesta. PDU puolestaan kostuu funk-

tion koodista ja datasta (Modbus 2004). Vaihtoehtoja protokollan viestintämuotoon on usei-

ta, mutta Ethernet-verkoissa käytetään Modbus TCP kehystä, jonka Modbus 2004 määritte-

lee seuraavan taulukon mukaisesti. Tässä taulukossa asiakas muodostaa kaikki nämä neljä

kohtaa. Palvelin puolestaan kopioi tunnisteet ja käyttää niitä, muodostaen oman vastausvies-

tinsä pituuskentän. Tämän kehyksen bittijärjestys on MSB (Most significant bit, merkittävin

bitti ensimmäisenä).

Nimi Pituus Kuvaus

Transaktion tunniste 2 tavua Synkronisaatio palvelimen ja asiakkaan välillä

Protokolla tunniste 2 tavua 0 = Modbus protokolla

Viestin pituus 2 tavua Viestin pituus kahdessa tavussa

Yksikön tunniste 1 tavu Slave-laitteen tunniste (255 jos ei käytössä)

Taulukko 1. Modbus TCP:n rakenne

12

3.3 PLC käyttötapauksia

Koska PLC:n sisäisen logiikan pystyy itse ohjelmoimaan, ovat sen käyttötapaukset erit-

täin vaihtelevia, mutta usein koordinaatiota vaativissa tehtävissä PLC-laitteisto yhdistetään

SCADA-ohjelmistoon (Fernandez Adiego, Prieto Barreiro ja Blanco Vinuela 2011). Useim-

mat automaatiojärjestelmät toimivat jonkinlaisella yhdistelmällä SCADA:a (Goldenberg ja

Wool 2013) sekä PLC:tä (Erickson 1996). PLC:n levinneisyys on sellainen asia, mitä harva

ihminen tulee edes ajatelleeksi. Näitä pieniä tietokoneita käytetään kaikkialla missä tarvitaan

automaatiota: tehtaissa, ydinvoimaloissa, metrojärjestelmissä ja niin edelleen.

Tämän projektin liikenteenhallinta sekä LVIS-laitteisto toimivat PLC:llä. Tämä tarkoittaa

esimerkiksi useita liikennevaloja, liikennepuomeja, kameroita, ilmanpuhaltimia, varoitus-

merkkejä, tieopasteita sekä kaikkea muuta mitä tämänkaltaiseen suureen tunnelijärjestel-

mään kuuluu. Kokonaisuuden hallitsemiseen tarvitaan SCADA:a (Supervisory Control and

Data Acquisition), eli tuttavallisemmin valvomo-ohjelmistoa.

13

4 SCADA

SCADA (engl. Supervisory Control And Data Acquisition) on tietokoneohjelmisto- tai arkki-

tehtuurityyppi, jolla yleisesti tarkoitetaan valvomo-ohjelmistoa. Kuten Boyer (2009) toteaa:

"SCADA teknologia on kehittynyt viimeisen 30 vuoden aikana suurien prosessien monito-

riontiin ja kontrolloimiseen."

Useimmiten SCADA:a käytetään PLC-laitteiston monitorointiin ja käskyttämiseen (Daneels

ja Salter 1999). Ajatus SCADA-ohjelmiston takana on saada hallitusti kerättyä tietoa useasta

lähteestä ja pystyä reagoimaan erilaisissa tilanteissa valvomon käyttöliittymän kautta, kuten

tulipalon syttyessä tai sähkövian ilmentyessä. SCADA-järjestelmät on usein myös mahdol-

lista kahdentaa: sama sovellus voi omata URI:n sekä aktiivisesta että passiivisesta palveli-

mesta, jolloin esimerkiksi yhteysvian sattuessa passiivisesta palvelimesta tulee sovelluksen

aktiivinen palvelin ja toisinpäin. SCADA-järjestelmän on tarkoitus olla ennen kaikkea luo-

tettava.

Usein nykyaikaiset valvomojärjestelmät kommunikoivat myös muiden järjestelmien kans-

sa, joko internetin tai kirjoittamansa tietokannan kautta. Tämä tosin on tuonut esiin huo-

mioita ja puutteita SCADA-järjestelmien tietoturvasta (Choi ym. 2010; Igure, Laughter ja

Williams 2006; Ten, Liu ja Manimaran 2008). Esimerkiksi Suomessa on neljä tieliikenne-

keskusta (Tampere, Helsinki, Turku, Oulu), joissa päivystetään tieliikennettä. Näiden kes-

kuksien valvomoissa on useita SCADA-ohjelmistoja joilla ohjataan liikenneympäristöä, ku-

ten tämän projektin tapauksessa. T-LOIK-hankkeen myötä liikennevirasto pyrkii yhtenäistä-

mään liikennekeskuksen päivystäjän työn yhden käyttöliittymän taakse, joka välittää viestit

eri SCADA ohjelmistoille. YSP Oy:n käyttämänä SCADA-ohjelmisto on WinCC Open Arc-

hitecture.

14

4.1 WinCC Open Architecture

WinCC OA on Siemens kehittämä SCADA-järjestelmä, jonka tarkoituksena on visualisoi-

da ja operoida erilaisia prosesseja, tuotantovirtoja, laitteita ja tehtaita kaikilla eri liiketoi-

minnan osa-alueilla. Ohjelmiston hajautettu rakenne mahdollistaa jopa 2048 ohjausjärjes-

telmän liittämisen toisiinsa saumattomasti (“The SCADA system without limits” 2018-08-

15). Lienee syytä mainita, että tässä puhutaan 2048:sta erillisestä järjestelmästä, eikä pel-

kästään yksittäisistä laitteista. Jokainen näistä järjestelmistä voi omata lukuisia eri yhteyksiä

eri PLC-laitteille. WinCC OA:n vahvuuksiin kuuluu sen tarjoama tehokkuus sekä skaalau-

tuvuus (Spangenberg, Cerff ja Kaiser 2011). WinCC OA:ta pystyy kustomisoimaan usealla

eri tavalla sekä se on alustariippumaton, eli siitä on myös saatavilla valmis jakelu Windows-,

Linux-, iOS- ja Android -käyttöjärjestelmille (“SIMATIC WinCC Open Architecture - Ba-

sic system” 2018-08-15). WinCC OA:n päälle on myös mahdollista suunnitella graafinen

käyttöliittymä.

Pähkinänkuoressa WinCC OA:n tarkoitus on siis kerätä ja välittää dataa useaan eri lähtee-

seen. Sen muokattavuuden yhdistäminen PLC-laitteistoon tarjoaakin erittäin paljon erilaisia

käyttötapauksia, mistä syystä WinCC OA:n käyttötarkoitukset sisältävät useanlaisia erilaisia

järjestelmiä. Näihin sisältyy esimerkiksi Norjan tieliikennekeskuksen liikenteenhallintajär-

jestelmä, ohjaus- ja virheenraportointi järjestelmä Sveitsin rautateille, Ranskan Besançonin

kaupungin katuvalaistuksen hallintajärjestelmä ja CERN-tutkimuskeskuksen hiukkasfysii-

kan laboratorion hallintajärjestelmä (“SIMANTIC WinCC Open Architecture - HMI Softwa-

re - Siemens” 2019-03-07).

WinCC OA:n ohjelmointikielenä toimii CTRL (control script language). CTRL:n syntaksi

perustuu ANSI-C:n standardiin (“Control script language” 2018-08-15), eli se on C:n va-

riantti, mikä tekee syntaksin opettelusta varsin triviaalia kokeneemmalle ohjelmoijalle. Ny-

kyään WinCC OA tarjoaa myös rajapinnan C#-ohjelmointikielelle, minkä kautta voi lukea

ja kirjoittaa prosessiarvoja, hälytyksiä ja historiadataa. WinCC OA tarjoaa myös rajapinnan

erilaisille tietokannoille kuten Access, Oracle ja Microsoft SQL (“Control script language”

2018-08-15). Tämä mahdollistaa esimerkiksi erillisen web-sovelluksen luomisen, mikä tark-

kailee WinCC OA:n käyttämän tietokannan dataa (Varela ym. 2018; Qiu ja Gooi 2000).

15

WinCC OA:lla on myös mahdollista luoda paneelitiedostoilla ja CTRL-skripteillä erilaisia

komponentteja sekä yhdistellä näitä graafisen käyttöjärjestelmän luomiseksi. Tämän ohjel-

miston suurin vahvuus on sen huomionarvoinen hajautettu arkkitehtuuri: järjestelmän eri

osat on luotu yksittäisiksi erilaisiksi komponenteiksi, joita WinCC OA:n prosessimanageri

tarkkailee ja käskyttää. Tällä periaatteella myös DriverManager rekisteröidään WinCC OA:n

prosessimanagerin prosessiksi. WinCC OA on siis ennen kaikkea hajautettu järjestelmä, jo-

ka rakentuu useista erilaisista komponenteista. Kun tähän käyttöliittymään yhdistää datan

vastaanottamisen ja välittämisen, on valvomo-ohjelmisto valmis.

4.2 Datan vastaanottaminen ja välitys WinCC OA:ssa

Datan kulkemisketju tapahtuu datapointeilla. WinCC OA:ssa asetetaan jokin tietty tunnis-

te datapointille. Tämä datapoint-rakenne voidaan myös konfiguroida kuuntelemaan Modbus

TCP-yhteyttä jostakin tietystä osoitteesta. Tämä ei tietenkään ole pakollista, eli datapoint-

teja voi myös käyttää väliaikaisena arvon säilytyspaikkana, johon C# API:n avulla voidaan

syöttää jotain dataa, jota myöhemmin sitten käsitellään WinCC OA:n sisäisissä operaatiois-

sa, kuten luvussa 8.4 esitetään. Jos datapoint sidotaan johonkin Modbus TCP -osoitteeseen,

osoitetta koskevaa liikennettä pystyy käsittelemään WinCC OA:ssa ja C#-rajapinnassa viit-

taamalla sen datapointtiin. Juuri tällä tavalla yksittäiset liikenteenhallinta laitteistot liitetään

valvomojärjestelmään, joka sitten antaa niille käskyjä kuten valon vaihtaminen tai liikenne-

puomin nostaminen.

Koska WinCC OA:n prosessiarvoja on mahdollista käsitellä eri ohjelmointikielillä ja se tarjo-

aa C#-rajapinnan, C# on erittäin looginen valinta kun WinCC OA:n tuottamaa dataa ruvetaan

tulkitsemaan ja välittämään muille sovelluksille.

16

5 REST-arkkitehtuuri & T-LOIK-Ohjaussovitin

REST (Representational State Transfer) on moderni arkkitehtuurimalli web-kehitykseen. Al-

lapiilevät ominaisuudet ovat hyvin ohjelmistokohtaisia, mutta REST-arkkitehtuurin ohjelmat

käyttävät aina HTTP-protokollan ominaisuuksia toteuttaakseen erilaisia operaatioita.

T-LOIK-Ohjaussovitin on REST-sovellus, jonka tarkoituksena on välittää T-LOIK:n viestejä

PLC-laitteistolle ja SCADA-järjestelmille. Se toimii liitoksena liikennejärjestelmiin, joita T-

LOIK ohjaa ja valvoo. Myös T-LOIK on REST-sovellus, joten kyseisen arkkitehtuurimallin

ymmärtäminen on olennaista kokonaiskuvan hahmoittamisen kannalta. Tässä luvussa pyri-

tään avaamaan REST-arkkitehtuuria sekä sen roolia moderneissa Suomen liikennejärjestel-

missä.

17

5.1 REST-arkkitehtuuri

REST-arkkitehtuurin tarkoituksena on jakaa web-sovelluksen eri toiminnallisuudet selkeästi

eroteltaviin kokonaisuuksiin. Arkkitehtuuri tarjoaa HTTP-protokollan yli erilaisia operaa-

tioita, jotka ovat mahdollisimman itsenäisiä, eivätkä omaa riippuvuuksia toisiin sovelluksen

operaatioihin. Kun sovellus toteuttaa REST-arkkitehtuurin, kutsutaan sovellusta RESTful-

sovellukseksi. Kuten Feng, Shen ja Fan (2009) toteavat: "REST-arkkitehtuuri ei ainoastaan

pysty hyödyntämään kaikkia HTTP-protokollan tarjoamia ominaisuuksia, vaan omaa myös

yksinkertaisuuden tarjoaman edun."

Kuusi suunnitelmallista periaatetta ohjaavat RESTful-kehitystä (Erl ym. 2012):

1 . Asiakas-palvelin -arkkitehtuuri

2 . Tilattomuus

3 . Välimuistiin tallentamisen mahdollisuus

4 . Kerroksittainen järjestelmätoteutus

5 . Koodin välitystä tarvittaessa ("Code on demand")

6 . Yhtenäinen rajapinta

Ensimmäinen periaate on hyvin yleinen web-sovelluksien kannalta: jokin järjestelmä toimii

palvelimena ja jokin asiakkaana, joka käyttää tämän palvelimen tarjoamia palveluja. Toinen

on puolestaan yleisimpiä REST-kehityksen periaatteita: REST-arkkitehtuurin mukaan teh-

dyn sovelluksen täytyy olla tilaton, eli jokainen operaatio on atominen eikä omaa jonkin

toisen operaation suorittamista esivaatimuksena. Kuten Rodriguez (2008) toteavat: "Tässä

yhteydessä tilattomuus parantaa web-palvelun suorituskykyä ja yksinkertaistaa palvelinpuo-

len komponenttien suunnittelua ja toteutusta, sillä tilan puuttuminen poistaa tarpeen synkro-

nisoida sessioiden dataa ulkoisten sovellusten kanssa."

Kolmas puolestaan on lähinnä sovelluksen suoritusnopeuden kannalta olennainen tekijä: vä-

limuistissa olennaisen tiedon säilyttäminen nopeuttaa ohjelman käyttöä ja vähentää latenssia

(Erenkrantz 2009). Välimuisti voi tässä tapauksessa olla palvelimen tai web-selaimen väli-

muisti.

18

Neljännen periaatteen mukaan REST-arkkitehtuuria seuraavassa sovelluksessa tarkoittaa kom-

ponenttien jakamista järkeviin kokonaisuuksiin, joissa matalamman tason resurssit tarjoavat

toiminallisuuksiaan ylemmille tasoille. Tällä toteutuksella järjestelmän komponentit eivät

tiedä mitään muista komponenteista, ainoastaan niistä joiden kanssa ne itse suoranaisesti

kommunikoivat (Chou ja Li 2016). Kyseessä on siis kapselointia vastaava periaate.

Viides kohta - eli koodin välitys tarvittaessa - on vapaaehtoinen, mutta toteutuu esimerkiksi

kun REST-sovellus tarjoaa web-selaimella Javascript-tiedostoja, joilla manipuloidaan web-

sivun sisältöä ja välitetään viestejä palvelimelle (Masse 2011).

Kuudes kohta on olennainen REST-sovelluksen kehitykseen ja jakautuu erinäisiin alakoh-

tiin, joiden tarkoituksena on tarkemmin määritellä kyseinen yhteinen rajapinta. Nämä koh-

dat ovat: pyydettyjen resurssien identifiointi palvelupyynnöissä, kuten tietyn URI:n kutsu-

minen tietyllä HTTP:n metodilla, resurssien manipulaatio representaatioiden kautta, atomi-

set viestit, eli jokainen viesti omaa kaiken operaatioon vaadittavan tiedon sekä HATEOAS

(Hypermedia as the engine of application state), eli hypermedia applikaation tilan mootto-

rina (Thijssen 2012). Palvelinpuoli vain suorittaa näitä atomisia operaatioita, ja sovelluksen

"tila"päätellään siitä mitä operaatiota kutsutaan.

T-LOIK-ohjaussovittimen tapauksessa kaikki kohdat paitsi viides toteutuvat - kyseinen so-

vellus ei omaa front endiä tai varsinaista käyttöliittymää, pelkästään RESTful operaatioita.

Esimerkiksi yksittäisen liikennevalon tilan hakemiseksi suoritetaan HTTP:n GET-operaatio

tiettyyn URL-osoitteeseen, kuten esimerkiksi https://www.server.org/liikennevalo/id/status.

Jos taas laitteen tilaa halutaan muokata, suoritetaan erilainen HTTP-operaatio, kuten POST

tai PUT eri URL-osoitteeseen. Jokainen aloituspiste ohjelmakoodin suoritukselle on sidottu

johonkin HTTP-metodiin (GET, POST, PUT, DELETE) sekä osoitteeseen. REST-arkkitehtuuri

seuraa CRUD-mallia (Create, Read, Update, Delete). Tämä malli asettaa raamit joiden mu-

kaisesti kyseinen sovellus toimii.

19

5.2 T-LOIK-Ohjaussovitin ja Akka.NET

Akka.NET on .NET versio Javan Akka-ohjelmistokirjastosta. Akka.NET perustuu Aktori-

suunnittelumalliin, jonka kehitti Carl Hewitt vuonna 1973 (Hewitt, Bishop ja Steiger 1973).

Akka.NET:in kehittäjien mukaan tämän kirjaston päämääränä on tarjota seuraavanlaisia toi-

mintoja (“What is Akka.NET?” 2018-08-15):

1 . Monisäikeistä käytöstä ilman matalan tason konstruktioita, kuten lukkoja ja atomisuutta

2 . Läpinäkyvää etäkommunikaatiota eri järjestelmien ja komponenttien välillä

3 . Klusteroitua ja skaalautuvaa arkkitehtuuria

Aktori-suunnittelumallissa pyritään tarjoamaan abstraktiota, joissa komponenteista tai jär-

jestelmistä tehdään omia aktoreitaan, jotka kommunikoivat keskenään asynkronisilla vies-

teillä metodikutsujen sijasta. Aktorit ylläpitävät ja hoitavat omaa tilaansa sekä reagoivat aina

vastaanottaessaan muutosviestin. Tämä reaktio voi olla esimerkiksi lapsi-aktorin luominen,

itsensä pysäyttäminen, lapsensa pysäyttäminen tai viestin välitys toisille aktoreille (“What is

Akka.NET?” 2018-08-15).

T-LOIK-Ohjaussovitin on adapteri-sovellus, joka välittää viestejä T-LOIK:n ja SCADA:n tai

PLC-laitteiden välillä. Sovelluksen tarkoituksena on integroida useita eri SCADA-järjestelmiä

ja PLC-laitteistoja T-LOIK:n käyttöliittymään, eli tulkita T-LOIK:n laittamien REST-kutsujen

sisällä kulkevasta XML:stä varsinainen komento ja muuttaa se joko SCADA:n tai PLC-

laitteen ymmärtämään muotoon.

T-LOIK-Ohjaussovittimen tapauksessa jokaista yksittäistä laitetta - kuten kamera, liikenne-

valo, tiedotusopaste, puomi ja niin edelleen - edustaa yksittäinen aktori, joka toteuttaa ky-

seisen laitteen vaatiman protokollan. Näitä protokolla-luokkia on tietenkin vain yksi, mutta

ohjelmiston ollessa ajossa jokaisesta laitteesta luodaan oma erillinen aktori-instanssinsa. Tä-

mä aktori on käytännössä C#-luokka, joka Akka.NET:iä hyödyntäen kuuntelee ja välittää

viestejä laitteen ja T-LOIK:n välillä. Yksittäiset laitteet määritellään rekursiivisessa XML-

tiedostossa. Esimerkiksi yksittäisen liikennevalon asetus voisi näyttää XML-muodossa tältä:

20

< a s e t u s n imi =" l i i k e n n e v a l o 1 " kuvaus =" l i i k e n n e v a l o n 1 a s e t u k s e t ">

< a s e t u k s e t >

< a s e t u s n imi =" i d " kuvaus =" l i i k e n n e v a l o n Id " a rvo =" 1 " / >

< a s e t u s n imi =" o s o i t e " kuvaus =" v a l o n ip−o s o i t e "

a rvo =" 1 2 7 . 0 . 0 . 1 " / >

< a s e t u s n imi =" p r o t o k o l l a " kuvaus ="AKKA. NET a k t o r i l u o k k a "

a rvo =" v a l o P r o t o k o l l a " / >

</ a s e t u k s e t >

</ a s e t u s >

Tämä aktori parsii T-LOIK:n REST-kutsulla lähettämän XML-tiedoston sisällöstä oleellisen

ohjauksen, muuttaa sen PLC-laitteen tai SCADA:n hyväksymään muotoon, suorittaa ohjauk-

sen, vastaanottaa kuittausviestin laitteelta ja parsii kuittausviestistä oleellisen tiedon ja kon-

vertoi sen takaisin T-LOIK:n hyväksymään XML-muotoon. Akka.NET siis toimii työkaluna,

jonka avulla PLC-laitteita saadaan käsiteltyä C#:n kaltaisen korkean tason ohjelmointikielen

vaatimalla abstraktiotasolla.

Esimerkiksi liikennevalojen suoraohjauksessa - eli ilman SCADA-järjestelmää - ohjaussovit-

timen liikennevalojen protokolla-aktori lukee tiedon kyseistä aktoria vastaavan laitteen IP-

osoitteesta ja eri funktiokäskyjen sijainnit PLC-laitteen muistirekisterissä sekä omaa tarvit-

tavat metodit tämän XML-käskyn konvertoimiseen muotoon, jonka PLC ymmärtää. Sinän-

sä ohjausmetodi on samanlainen myös WinCC OA-järjestelmien kanssa: erona on lähinnä

se, että muistiavaruuden osoitteiden ja hexalukujen sijasta käskyjä välitetään datapointteihin

WinCC OA:n tukemassa muodossa. T-LOIK-ohjaussovittimen toimintaa kuvaa kuviossa 4

oleva tietovuokaavio:

21

Kuvio 4. T-LOIK-ohjaussovittimen tietovuo-kaavio

22

T-LOIK:in ohjatessa liikennevaloa T-LOIK laittaa verkon yli ohjaussovittimelle REST-kutsun,

joka sisältää XML-datana esitetyn ohjauskäskyn. Ohjaussovitin lukee tämän käskyn, etsii sa-

maa laitetyyppiä ja saman tunnisteen omaavan protokolla-aktorin ja lukee protokolla-aktorin

luokan tiedoista sen IP-osoitteen sekä muut relevantit tiedot, minkä jälkeen ohjaussovitin

suorittaa funktion, joka muokkaa tästä XML-käskyn datasta aktori-luokan määrittelemän ta-

vutaulukon tai SCADA:n tapauksessa jonkin muun tietotyypin, jonka ohjaussovitin välittää

PLC-laitteelle tai SCADA-järjestelmään. Samalla logiikalla välitetään tietoja PLC-laitteista

ja SCADA-järjestelmistä T-LOIK:iin, nämä operaatiot vain suoritetaan päinvastaisessa jär-

jestyksessä.

T-LOIK-Ohjaussovitin toteuttaa usean eri suunnittelumallin ominaisuuksia:

1 . AKKA.NET-kirjaston tarjoaminen aktoreiden avulla kyseinen applikaatio toteuttaa

Aktori-suunnittelumallin (Actor Model).

2 . T-LOIK sekä T-LOIK-Ohjaussovitin voivat kummatkin toimia sekä palvelimena että

asiakkaana, kommunikoiden keskenään REST-kutsuilla ja XML-tiedostoilla, joten se

toteuttaa myös kahdensuuntaisen palvelin-asiakas-suunnittelumallin.

3 . Viestinvälittäjä-suunnittelumalli (Broker pattern) toteutuu, sillä T-LOIK:illa voi olla

monta instanssia eri palvelimilla, mitkä kommunikoivat saman ohjaussovittimen kautta

PLC-laitteistolle ja SCADA-järjestelmille.

4 . Modbus TCP:n toteuttamisen seurauksesta myös master-slave -arkkitehtuuria

hyödynnetään paljon.

5 . SCADA-järjestelmien tavoin ohjaussovitin on mahdollista kahdentaa kahden eri

palvelimen toimintaan, jotka tarvittaessa vaihtavat aktiivisen ja passiivisen palvelimen

välillä. (Hot Standby)

Tämän ohjelmiston avulla SCADA-järjestelmä ja sen aliprosessiksi rekisteröity XaidDriver

yhdistyvät T-LOIK:n järjestelmään.

23

6 Managed Extensibility Framework & DriverManager

MEF (Managed extensibility framework) on .NET 4.0 versiossa ensijulkaisunsa kokenut

Microsoftin ohjelmistokirjasto (“Managed Extensibility Framework (MEF)” 2018-09-24).

MEF:in päätarkoitus on helpottaa ohjelmiston laajentamista, sillä se sallii laajennusten koo-

din helpon kapseloinnin erillisiksi komponenteiksi, joita uudelleenkäytetään eri sovelluksien

välillä ilman kovakoodattujen riippuvuuksien muodostamista (“Managed Extensibility Fra-

mework (MEF)” 2018-09-24). DriverManager on C#-ohjelmointikiellä rakennettu ajurialus-

ta WinCC OA -ohjelmille, joka on toteutettu .NET-kirjaston MEF-kirjastolla.

MEF-komponentit rekisteröidään isäntä-sovellukseen pelkällä konfiguraatio-tiedostolla, jon-

ka jälkeen sovellus pystyy käyttämään näitä komponentteja. MEF tarjoaa tavan löytää uudet

komponentit implisiittisesti: MEF-komponentti ilmaisee konfiguraatio-tiedostossa sekä riip-

puvuutensa että tarjoamansa ominaisuudet. Kun yksittäinen MEF-komponentti (kutsutaan

nimellä part) liitetään ohjelmistoon, MEF-kehyksen koostaja-moottori (MEF composition

engine) liittää sen tarjoamat toiminnallisuudet muihin MEF-komponetteihin (“Managed Ex-

tensibility Framework (MEF)” 2018-09-24).

Tässä käyttötapauksessa DriverManager on MEF-applikaatio, joka kuuntelee WinCC OA:n

Datapointtien muutoksia ja toteuttaa niiden perusteella jotain operaatioita. DriverManagerin

sekä ajurien mahdolliset riippuvuudet sijoitetaan WinCC OA:n kansiorakenteen sisälle, jol-

loin Win CC OA:n projektimanageri löytää DriverManagerin .exe-tiedoston. Tämän jälkeen

DriverManager rekisteröidään SCADA-järjestelmän projektimanageriin. Rekisteröinnin jäl-

keen projektimanageri hoitaa DriverManagerin käynnistämisen, sulkemisen, uudelleenkäyn-

nistämisen ja yleisen monitoroinnin. DriverManagerin konfiguraatiotiedostoon määritetään

ajurien kansiosijainti. XaidDriverin koodin kääntämisestä syntynyt .dll-tiedosto sijoitetaan

tietokoneella tähän määriteltyyn kansioon, jonka jälkeen DriverManager löytää ja käynnis-

tää tämän ajurin.

24

Kuvio 5. DriverManager WinCC OA:n projektimanagerin aliprosessina

Kuviossa näkyy esimerkkikonfiguraatio WinCC OA:n projektinhallinta konsolista, jossa lis-

tataan ohjelmaan ladatut erilliset komponentit, joita projektimanageri monitoroi. Viimeisenä

prosessina näkyy WCCOADriverManager. DriverManager toimii MEF-sovelluksen liitos-

kohtana WinCC OA-ohjelmistolle: konfiguraatiot toteutetaan JSON-muodossa. Esimerkik-

si XaidDriverin konfiguraatio, joka sijoitetaan WinCC OA-järjestelmän tietorakenteeseen,

näyttää simulaatiotilanteessa seuraavalta:

25

{

" i n p u t " : {

" x a i d " : {

" managerNumber " : 1 ,

" a c t i v e " : 1 ,

" connect ionName " : " xa id −1" ,

" a d d r e s s " : " h t t p : / / l o c a l h o s t : 1 1 1 8 0 / x a i d / " ,

" r ed un da nc yAd dr e s s " : " h t t p : / / l o c a l h o s t : 1 1 1 8 1 / x a i d / " ,

" oldNewComparison " : true ,

" p o r t " : " 9991 " ,

" r e d u n d a n c y P o r t " : " 9992 " ,

" i p " : " 1 2 7 . 0 . 0 . 1 " ,

" r e d u n d a n c y I p " : " 1 2 7 . 0 . 0 . 1 " ,

" c r e a t e X a i d D a t a p o i n t s " : f a l s e

}

}

}

DriverManager kyselee ja lukee nämä tiedot SCADA-järjestelmän tietorakenteesta. Käyn-

nistyessään se kyselee jokaisen datapointin yleiset konfiguraatiot ja etsii ennaltamääritel-

lystä paikasta tämänkaltaisia konfiguraatiotietoja. Output- ja input-kenttien sisällä olevan

olion nimi määrittelee etsittävän ajurin. Esimerkiksi XaidInputDriver-luokassa on luokan

nimeksi määritelty "xaid", joten DriverManager osaa yhdistää tämän konfiguraatiotiedos-

ton ja löytyneen ajurin .dll-tiedoston. Tämä mahdollistaa ohjelman vaatimien peruspara-

metrien välityksen: tämän JSON-tekstin lukeminen string-muuttujasta tarjoaa XaidDrive-

rille HTTP-rajapinnan osoitteen sekä TCP-yhteyden IP-osoitteen ja portin. Näillä tiedoilla

MEF-applikaatio käynnistää ajurin ja aloittaa välittämään dataa SCADA-järjestelmän ja X-

AID-järjestelmän välillä.

Osasta datapointeista halutaan myös ajonaikaisesti lukea dataa JSON-muodossa. Tällaisten

datapointtien sisään sijoitetaan aiemman kaltainen output-JSON, joka näyttää seuraavalta:

26

{

" o u t p u t " : {

" x a i d " : {

" managerNumber " : 1 ,

" a c t i v e " : 1 ,

" t y p e " : " camera " ,

" i d " : 9010 ,

" s e r v e r I d " : 1 ,

" connect ionName " : " XaidCam−HKA10" ,

" c o n n e c t i o n S t r i n g " : " h t t p : / / l o c a l h o s t : 1 1 1 8 0 / x a i d / s i m u l a t o r / "

}

}

}

Tämä JSON kertoo DriverManagerille, että tämän datapointin arvojen muutosta halutaan

kuunnella. Output-avaimen alla oleva xaid-avain puolestaan kertoo ajurin nimen. Tämä sallii

tämän datapointin kenttien arvojen lähettämisen XaidOutputDriver-luokan funktiolle Out-

putChangedAsync, joka sitten tulkitsee arvoja ja suorittaa parametrisoituja toimintoja.

27

7 X-AID häiriönhavaintojärjestelmä ja testivetoinen

kehitys

X-AID häiriönhavaintojärjetelmä on keinoälyä ja koneoppimista hyödyntävä liikenteen mo-

nitorointijärjestelmä. X-AID on AVID (Automatic Video Incident Detection) järjestelmä, eli

koneoppimista hyödyntävä X-AID-palvelin analysoi jatkuvalla syötöllä sille saapuvaa video-

kuvaa liikenteestä. Tämän projektin tapauksessa X-AID-järjestelmä valvoo tunnelin liiken-

nettä mahdollisissa ongelmakohdissa ja välittää viestejä valvomoon. Hälytyksien lauetessa

PLC-laitteisto laukaisee erilaisia liikenteenohjaus-sekvenssejä. Nämä sekvenssit esimerkiksi

sulkevat kaistoja, vaihtavat liikennevaloja punaisiksi, sulkevat liikennepuomeja ja vaihtavat

tieopasteiden tekstejä. Tämän tarkoituksena on lisätä liikenteen turvallisuutta ja sujuvuutta,

vähentäen vaaratilanteita.

X-AID häiriönhavaintojärjestelmän kanssa kommunikoidaan pääasiallisesti TCP-yhteydellä.

Järjestelmä omaa myös yksinkertaisen HTTP-rajapinnan, jonka kautta pystyy esimerkiksi

lataamaan johonkin tiettyyn hälytykseen sidotun videotiedoston. X-AID-palvelimen lähettä-

mästä tavutaulukosta tulkitaan varsinainen viestisisältö käsittelemällä tavutaulukkoa X-AID-

protokollan määritelmien mukaisesti. Tavutaulukko sisältää erilaisia muuttujatyyppejä, ku-

ten char, UInt32, UInt16 ja niin edelleen, joita parsitaan protokollan määritelmien mukaises-

ti. Varsinainen X-AID protokollan tekninen toteutus ja viestisisältö on määritelty järjestel-

män toimittajan tarjoamassa dokumentissa 2017-098-T004-V1r5 - External TCP Interface -

Technical Specification.pdf.

Onnistunut integraatio valvomojärjestelmiin ja tieliikenteen ohjausjärjestelmiin vaatii TCP-

datan reaaliaikaista lukemista, protokollan tulkkaamista ja viestien välittämistä SCADA:n

kautta PLC:lle ja takaisin. Jotta viestien välitys SCADA:n ja PLC:n suuntaan toimisi mahdol-

lisimman esteettömästi, toteutettiin kyseinen tulkkiohjelma TCP-kuuntelijana DriverMana-

gerin ajuriksi. Ajuri muodostaa myös aiemmin mainittuja HTTP-rajapinnan URL-osoitteita,

jotka välitetään SCADA:n kautta T-LOIK:iin. Tätä kautta T-LOIK ja SCADA pystyvät la-

taamaan hälytystapahtumista videotiedoston sekä kuvan HTTP:n kautta, ilman tarvetta TCP-

virran tulkkaamiselle.

28

7.1 Kuvaus X-AID häiriönhavaintojärjestelmästä

Järjestelmän toimittajan mukaan (“Traffic Video Analysis / Automatic Video Incident De-

tection - XAIDTM” 2018-09-27) osa-alueet joilla X-AID:ia voi hyödyntää ovat:

1 . Liikennevideoiden analysointi

2 . AVID-monitorointi tie-, tunneli- ja siltaosuuksilla

3 . Liikennerikkomusten ja epäsäännöllisyyksien havainnointi

4 . Liikenteen sujuvuuden monitorointi

Käytännössä X-AID vastaanottaa jatkuvaa videokuvaa tarkkailemastaan alueesta ja hälyt-

tää TCP:n kautta ajuria, jos epäsäännöllisyyksiä ilmenee. X-AID-järjestelmään ohjelmoidut

hälytykset ovat (“Traffic Video Analysis / Automatic Video Incident Detection - XAIDTM”

2018-09-27):

1 . Väärään suuntaan ajava ajoneuvo

2 . Pysähtynyt ajoneuvo

3 . Liikenneruuhka

4 . Hidas ajoneuvo

5 . Kävelijä

6 . Alentenut havainnointitaso (sumua, savua jne.)

7 . Esteitä tiellä

8 . Ajoradan ulkopuolella ajaminen

9 . Rekka-auto/Hidas ajoneuvo ohituskaistalla

1 0 . Keltaisen linjan ylitykset

1 1 . Ansalanka tiellä

Tästä listauksesta olennaisia tämän pro gradun kannalta ovat kohdat 1, 2 ja 4, sillä nämä

hälytykset ovat ainoat tässä projektissa huomioon otettavat hälytykset. Juuri hälytykset 1,2

ja 4 toimivat laukaisimina PLC-laitteiston suorittamille liikenteehallinta-sekvensseille.

29

7.2 X-AID-simulaattori

X-AID-järjestelmän (Automatic Video Incident Detection (AVID)) protokollatulkin kehitys-

tä varten järjestelmän toimittanut yritys tarjosi YSP Oy:lle käyttöön X-AID-simulaattorin.

Tämä simulaattori on toimitettu komentorivillä ajettavana .exe-tiedostona, joka pystyttää pai-

kallisen palvelimen ja ajaa simulaattoria.

X-AID-simulaattori tarjoaa sekä TCP-rajapinnan, jonka kautta pääasiallinen kommunikaa-

tio tapahtuu, sekä HTTP-rajapinnan, jolla pystyy aktivoimaan ja deaktivoimaan simuloituja

hälytyksiä. Tämä mahdollistaa TCP-yhteyden ottamisen ja hälytyksien simuloinnin HTTP:n

yli, jolloin TCP-yhteyden kautta saapuu informaatiota kyseisestä hälytyksestä.

Tarkemmat protokolla-määritelmät on myös tarjottu .pdf-tiedostoina. Näissä dokumenteissa

määritellään tavutaulukkojen sisältö, protokollan rakenne ja sopivat C#-ohjelmointikielen

tietotyypit sekä HTTP-kutsut joilla saa laukaistuja simuloituja hälytyksiä. Jokaisella viestillä

on 16 tavun otsikko, jonka jälkeen seuraa varsinainen tietosisältö, jota tulkitaan järjestelmän

toimittajan tarjoaman TCP-rajapinnan dokumentaation mukaisesti.

X-AID-simulaattori toimii varsinaisen kehitystyön selkärankana, sillä ottamalla TCP-yhteyden

simulaattoriin ja laukaisemalla hälytyksiä HTTP-kutsuilla pystyy palvelimelta vastaanotta-

maan simuloituja hälytyksiä, jotka vastaavat oikean elämän tilanteiden laukaisemia hälytyk-

siä. Näiden simuloitujen tilanteiden käsittely tapahtuu siis aivan samalla tavalla kuin oikeas-

sakin tilanteessa, mikä mahdollistaa itse protokollatulkin kehityksen.

Protokollamääritelmä tarjoaa myös selkeää osviittaa luokkasuunnitteluun, sillä on vähem-

män työlästä käyttää luokkasuunnittelun pohjana jo valmiiksi tässä dokumentissa määritel-

tyjä luokkarakenteita. Joka tapauksessa kyseisen simulaattorin tarjoama etu on huomattava

verrattuna esimerkiksi tilanteeseen, jossa olisi tarjolla vain .pdf-tiedosto protokollamääritel-

mistä. Tällöin järkevintä olisi kehittää simulaattori varsinaisen protokollatulkin kehityksen

ohessa. Lähtökohdat huomioon ottaen viisain tapa kehittää kyseinen ajuri on siis testivetoi-

nen kehitys (Test Driven Development).

30

7.3 Testivetoinen kehitys

Testivetoinen kehitys (Test Driven Development, TDD) on tapa suunnitella ohjelmistoja.

Aluksi vaatimuksista eritellään selkeät käyttötapaukset, joiden perusteella rakennetaan yksikkö-

ja integraatiotestit. Tämän jälkeen testejä vasten kehitetään itse ohjelmistoa, eli testit kirjoi-

tetaan ennen varsinaista ohjelman sisältöä. Testivetoisen kehityksen prosessin pystyy jaotte-

lemaan viiteen osaan (Beck 2003):

1 . Luo testi

2 . Aja testit ja katso epäonnistuuko kyseinen uusi testi

3 . Kirjoita koodi

4 . Aja testit

5 . Refaktoroi koodi

Tämän kehitystavan päämääränä on tuottaa helposti luettavaa ja siistiä koodia (Beck 2003).

Tarkoituksena on siis luoda epäonnistuvia testejä, luoda koodia joka toteuttaa testin läpäi-

semiseen vaadittavat operaatiot ja testien läpäisemisen jälkeen suorittaa tarvittavaa refakto-

rointia.

Testivetoisen kehityksen etuja ja haittoja on tarkasteltu useassa eri tutkimuksessa: esimer-

kiksi George ja Williams 2004 suorittivat kokeen, jonka tuloksista huomattiin, että testi-

vetoista kehitystä toteuttaneiden ohjelmoijien koodi oli parempilaatuisempaa, sillä heidän

koodinsa läpäisi 18% enemmän black-box testeistä kontrolliryhmään verrattuna. Tosin hait-

tana huomattiin, että testivetoista kehitystä toteuttavilla ohjelmoijilla kesti keskimäärin noin

16% enemmän aikaa. Myös IBM:n suorittamassa kokeessa (Maximilien ja Williams 2003)

huomattiin, että testivetoisen kehityksen avulla defektien määrä laski noin 50%. Automaa-

tiojärjestelmissä luotettavuus on luonnollisesti hyvin tärkeää, joten testivetoisen kehityksen

vahvuudet kannattaa hyödyntää tämän järjestelmäintegraation toteutuksessa.

31

8 XaidDriver

XaidDriver on X-AID-palvelimen rajapinta SCADA-järjestelmään. XaidDriver sijaitsee Dri-

verManagerin ajurina, joka toimii myös X-AID-järjestelmän välittämän TCP-protokollan

tulkkina sekä tämän suunnittelututkimuksen varsinaisena kohteena.

Hevner ja Chatterjee (2010) määrittelevät suunnittelututkimukselle kahdeksan eri kohtaa,

joihin tutkimuksen pitäisi pystyä vastaamaan:

1 . Mikä on tutkimuskysymys? Mitkä ovat vaatimukset?

2 . Mikä on suunnittelututkimuksen artifakti? Miten artefaktin toiminnot ilmenevät?

3 . Mitä suunnitteluprosesseja tai heurestiikkoja käytetään artefaktin rakennuksessa?

4 . Miten artefakti on sidonnainen todellisuuteen? Mitkä teoriat tukevat artefaktin

suunnittelua ja suunnitteluprosessia?

5 . Mitä evaluaatioita suoritetaan suunnittelusyklien aikana?

6 . Kuinka artefakti liitetään sovellusten ympäristöön ja kuinka sitä kenttätestataan?

7 . Mitä uutta tietoutta tämän artefaktin suunnittelusta syntyy?

8 . Onko suunnittelukysymykseen vastattu?

Tässä tapauksessa tutkimuskysymys on kuinka tämänkaltainen häiriöhavaintojärjestelmä in-

tegroidaan liikenteenhallintajärjestelmään. Tähän kysymykseen sisällöllisesti vastaa koko

tutkielma. Vaatimukset myös määritellään erikseen myöhemmin luvussa 8. Suunnittelututki-

muksen artefakti puolestaan on X-AID-järjestelmän valvomo-ohjelmiston ajuri, eli XaidDri-

ver. Suunnittelussa käytettyjä suunnittelumalleja ja heurestiikkoja käydään läpi luvussa 8.2

sekä luvussa 8.1. Evaluaatioina puolestaan toimivat yksikkötestit, integraatiotestit sekä kent-

tätestit, joita käydään läpi luvussa 9. Ajurin integraatiota olemassaolevaan ympäristöön puo-

lestaan avataan luvussa 8.3. Tutkimuskysymykseen vastaaminen ja uuden tiedon syntymistä

puolestaan pohditaan luvussa 10.

Aiemmin mainitun mukaisesti XaidDriver toteutettiin DriverManagerin ajuriksi, jotta kom-

munikointi WinCC OA:n suuntaan on helpompaa. Tämän lisäksi kehityksessä hyödynne-

tään ProtoLib-ohjelmistokirjastoa, joka on yleinen protokollakirjasto. Tämän protokollakir-

32

jaston tarkoitus on yksinkertaistaa TCP- tai UDP-yhteyksien luomista, sillä se on geneeri-

nen protokollatulkki-ohjelmistokirjasto. ProtoLib tarjoaa muutaman pakollisen toteutettavan

rajapinnan: IEncoder, IDecoder ja IMessageHandler. Näihin rajapintoihin kirjoitetaan sovel-

luskohtaiset koodit, mutta muuten itse kirjaston alustaminen on varsin yksinkertaista, kuten

luvun 8 koodista havaitsee.

ProtoLib-protokollakirjasto perustuu DotNetty-kirjastoon, joka on käännös Javan Netty-kirjas-

tosta. Hyödyntämällä näitä olemassaolevia kirjastoja ja komponentteja itse kehitystyössä

säästetään paljon aikaa. Muun muuassa SCADA-järjestelmän datanvälityksen kahdennuksen

ja TCP-protokollatulkin perustoimintojen toteutuksen pystyy näin hyvin pitkälti ohittamaan.

Suurin osa työstä menee siis protokollakohtaisten enkoodereiden ja dekoodereiden rakenta-

miseen, datan mallintamiseen C#-luokiksi ja useiden eri komponenttien integraatioon.

Ajuri on TCP-asiakas. Se pyörii DriverManagerin päällä ikuisessa silmukassa ja ottaa ti-

lattomasti DotNettyä hyödyntävän ProtoLibin avulla vastaan X-AID-palvelimen lähettämiä

viestejä ja parsii niistä C#-representaatiot sekä välittää vastaanottamaansa tietoa SCADA:n

kautta PLC:lle ja takaisin PLC:ltä SCADA:n kautta palvelimelle. Pääasialliset toiminnalliset

vaatimukset ovat seuraavat:

1 . Ajuri tulkkaa ja muodostaa X-AID protokollan määritelmän mukaisia viestejä

2 . Ajuri lähettää ja vastaanottaa dataa X-AID-järjestelmän ja SCADA-järjestelmän välillä

3 . Ajuri koostaa X-AID -järjestelmän lähettämän datan perusteella luokkarakenteet ja

välittää sen tiedot SCADA:an.

4 . Ajuri ylläpitää omissa malli-luokissaan järjestelmän tämän hetkistä tilaa.

5 . Järjestelmä koittaa uudelleenyhdistää X-AID -järjestelmään yhteysvian sattuessa.

6 . Järjestelmä osaa uudelleenkäynnistyä tietokoneen kaatuessa.

7 . Järjestelmä osaa tunnistaa kumpi palvelimista on tällä hetkellä aktiivinen ja kumpi

passiivinen

8 . Järjestelmä on luotettava, sillä se tulee pyörimään kellon ympäri SCADA:n

aliprosessina.

9 . Järjestelmä osaa alustaa itsensä asennuksen ja käynnistyksen tapahtuessa

1 0 . Järjestelmä kykenee asettamaan erilaisia suodattimia, joilla disabloidaan esimerkiksi

33

yksittäisten kameroiden aiheuttamat hälytykset

1 1 . Järjestelmä kykenee vaihtamaan aktiivisen ja passiivisen X-AID palvelimen välillä

mahdollisen yhteysvian sattuessa

Kuudennen kohdan hoitaa aiemmin mainittu WinCC OA:n prosessimanageri Pmon, jon-

ka aliprosessiksi DriverManager rekisteröityy. Seitsemäs kohta puolestaan on jo toteutet-

tu DriverManager-ohjelmistossa, jonka ajuriksi XaidDriver rekisteröityy. Toinen kohta vaa-

timuksista on toteutettu ProtoLib-kirjaston avulla, joka alustetaan DriverManagerin Input-

rajapinnan toteuttavassa XaidInputDriver-luokassa. ProtoLib-kirjaston alustuksen toteuttava

funktio näyttää seuraavanlaiselta:

/ / / <summary>

/ / / I n i t i a l i z e s t h e p r o t o l i b i n s t a n c e

/ / / </ summary>

/ / / <param name=" p o r t " > </ param >

/ / / <param name=" i p " > </ param >

p u b l i c P r o t o L i b C l i e n t I n i t i a l i z e P r o t o l i b ( s t r i n g p o r t , s t r i n g i p )

{

Logger . I n f o ( " I n i t i a l i z i n g p r o t o l i b " ) ;

S o c k e t C h a n n e l C o n f i g _ s o c k e t C h a n n e l = new

S o c k e t C h a n n e l C o n f i g . S o c k e t C h a n n e l C o n f i g B u i l d e r ( )

. Se tKeepAl ive ( t rue )

. B u i l d ( ) ;

_ c l i e n t C o n f i g = new C l i e n t C o n f i g B u i l d e r ( )

. S e t C h a n n e l C o n f i g ( _ s o c k e t C h a n n e l )

. S e t S e r v e r I p A d d r e s s ( IPAddres s . P a r s e ( i p ) )

. S e t S e r v e r P o r t ( i n t . P a r s e ( p o r t ) )

. B u i l d ( ) ;

_ f r ameDecoderConf ig = new

34

L e n g t h F i e l d B a s e d F r a m e D e c o d e r C o n f i g B u i l d e r ( )

. S e t B y t e O r d e r ( By teOrder . L i t t l e E n d i a n )

. S e t L e n g t h F i e l d O f f s e t ( 4 )

. S e t L e n g t h F i e l d L e n g t h ( 4 )

. S e t L e n g t h A d j u s t m e n t (−8)

. SetMaxFrameLength ( I n t 3 2 . MaxValue )

. S e t F a i l F a s t ( t rue )

. B u i l d ( ) ;

_ d e c o d e r B u i l d e r = new

R e s p o n s e D e c o d e r S e r v i c e . R e s p o n s e D e c o d e r B u i l d e r ( )

. S e t O b s e r v e r ( t h i s ) ;

_ e n c o d e r B u i l d e r = new

R e q u e s t E n c o d e r S e r v i c e . R e q u e s t E n c o d e r B u i l d e r ( ) ;

_messageHand le r = new MessageHandler ( new TimeSpan ( 0 , 0 , 60) ,

new TimeSpan ( 0 , 0 , 60) ) ;

_ c l i e n t B u i l d e r = new C l i e n t B u i l d e r ( )

. S e t C l i e n t C o n f i g ( _ c l i e n t C o n f i g )

. Se tFrameDecoderConf ig ( _ f rameDecoderConf ig )

. S e t D e c o d e r B u i l d e r ( _ d e c o d e r B u i l d e r )

. S e t E n c o d e r B u i l d e r ( _ e n c o d e r B u i l d e r )

. Se t InboundMessageHand le r ( _messageHand le r ) ;

re turn _ c l i e n t B u i l d e r . B u i l d ( ) ;

}

Loput listauksessa esille tulleet kohdat on toteutettu ajuriin, jonka rakenne ja sovelletut suun-

nittelumallit sekä vaatimusten täyttyminen käydään läpi tarkemmin seuraavissa luvuissa.

35

8.1 Oliosuunnittelu ja XaidDriver

Koska kyseessä on integraatioprojekti ja kyseisessä projektissa on tarjottu avuksi järjestel-

män tarjoajan kehittämä simulaattori sekä kyseisen simulaattorin dokumentaatio, on hel-

pointa aloittaa oliosuunnittelu sekä testien suunnittelu seuraamalla kyseisen dokumentaation

datarakenteita.

Palvelimelta vastaanotetuista viesteistä mallinnettiin C#-luokkia ja luokkien sisältöjen pe-

rusteella niistä muodostettiin hierarkia. Hierarkian perusteella nämä luokat voi luokitella

kolmeen eri pääkategoriaan:

1. Koko järjestelmän laajuista informaatiota tai asetuksia. Näiden kantaluokkana toimii Xaid-

SystemParameters.

2. Analysaattori-palvelimet ja niihin liittyvät luokat. Kantaluokkana toimii Server.

3. Yksittäiset kamerat. Jokaisella kameralla on tila, asetukset, isäntäpalvelin, kaistakohtaisia

tilastoja ja erilaisia hälytyksiä. Kantaluokkana toimii Camera.

Toiminnallisuuksien perusteella eritelty arkkitehtuurikuvaus tiedonkulusta ja ohjelmiston

tehtävistä on seuraavanlainen:

36

Kuvio 6. XaidDriverin arkkitehtuuri

37

Tässä kuvataan SCADA:n aliprosessina toimivan DriverManagerin suhde XaidDriveriin se-

kä XaidDriverin suhde sen hyödyntämään ProtoLib-kirjastoon. WinCC OA:n C#-Manager

on C#-rajapinta WinCC OA:lle, jota DriverManager käyttää. XaidDriver hoitaa arvojen päi-

vittämisen DriverManagerin kautta, mutta ohjelman alustuessa ensi kertaa se käyttää itsel-

leen injektoitua referenssiä C#-Manageriin ja luo sen avulla ajurin vaatimat datarakenteet

WinCC OA -järjestelmään. DatapointModifer-luokka siis toteuttaa luvun 8 vaatimusten koh-

dan numero 9.

XaidInputDriver ja XaidOutputDriver toteuttavat DriverManagerin määrittelemät rajapinta-

vaatimukset ja rekisteröityvät DriverManageriin. Molemmat näistä omaavat funktiot, jotka

käynnistyvät kun WinCC OA:n datapoint arvot muuttuvat. Lienee silti tärkeää huomata, että

DriverManager tarkkailee vain datapoint-rakenteita joissa on erikseen määritelty konfiguraa-

tioissa DriverManagerin vaatima asetus JSON-tiedosto, kuten kappaleessa 6 esitettiin. Kum-

matkin näistä luokista omaavat XaidSingleton-luokan avulla referenssin samaan staattiseen

ajuriin. Tämän ajurin pääasiallinen luokka on XaidDriver.

XaidDriver on ajurin kantaluokka. Tämä luokka omaa ajantasalla olevat tiedot X-AID-järjestel-

män tämänhetkisestä tilasta. Kommunikaation X-AID-järjestelmään XaidDriver toteuttaa

hyödyntämällä ProtoLib-ohjelmistokirjastoa, toteuttamalla sen vaatimat rajapinnat: IClient-

MessageHandler, IDecoder ja IEncoder. IClientMessageHandlerin rajapinnan toteuttaa Mes-

sageHandler-luokka, joka omaa viestien lukemisen ja lähettämisen lisäksi muun muassa toi-

minnallisuudet viestijonojen luomiseen sekä virheenkäsittelyyn. XaidDecoder ja XaidEnco-

der puolestaan toteuttavat rajapinnat IDecoder ja IEncoder. Koska XaidDriver säilyttää tul-

kattavien olioiden tilan ja rakenteen, se toteuttaa luvun 8 vaatimusten kohdan numero 4.

XaidDriver omaa myös ajastimen, jonka perusteella lähetetään protokollamäärityksen mu-

kaista ping-viestiä viiden sekunnin välein. Tämä johtuu siitä, että X-AID-järjestelmä sulkee

yhteyden mikäli asiakas ei lähetä yhteyden ylläpitoviestiä 10 sekunnin välein. Tämä funktio

näyttää seuraavanlaiselta:

/ / / <summary>

/ / / Sends p ing message t o X−AID s e r v e r .

38

/ / / </ summary>

p u b l i c a sync vo id SendPingMessage ( )

{

i f ( ! _hostName . Equ a l s ( Envi ronment . MachineName ) )

{

i f ( _ c l i e n t . A c t i v e ) a w a i t _ c l i e n t . CloseAsync ( ) ;

i f ( _ r e d u C l i e n t != n u l l && _ r e d u C l i e n t . A c t i v e ) a w a i t

_ r e d u C l i e n t . CloseAsync ( ) ;

re turn ;

}

i f ( _ c l i e n t . A c t i v e )

{

t r y

{

a w a i t SendReques t ( Command . KeepAlive ,

( u long ) 123456178910 , MessageId , 24) ;

}

c a t c h

{

Logger . E r r o r ( $ " E x c e p t i o n o c c u r r e d w h i l e s e n d i n g a

r e q u e s t t o X−AID s e r v e r . " ) ;

a w a i t CheckForRedundancy ( ) ;

}

}

e l s e

{

t r y

{

a w a i t Connect ( ) ;

}

c a t c h

{

39

Logger . E r r o r ( $ " Couldn ’ t r e c o n n e c t t o Xaid−S e r v e r ! " ) ;

a w a i t CheckForRedundancy ( ) ;

}

}

}

Tämä funktio siis yrittää myös uudelleenyhdistää ajurin X-AID-palvelimelle, mikäli yhteys

on katkennut. Funktion alussa myös tarkistetaan, että tämä instanssi ajurista on aktiivisella

SCADA-palvelimella sijaitseva instanssi. Mikäli näin ei ole, suljetaan yhteys eikä yhteyt-

tä enää oteta, ellei aktiivisen palvelimen nimi vaihdu kyseisen tietokoneen nimeksi. Tämän

avulla siis toteutetaan luvun 8 vaatimusten kohta numero 5 ja varmistetaan kohdan numero 7

toteutuminen. Samalla mahdollisten yhteysongelmien sattuessa tämä funktio koittaa vaihtaa

aktiivisesta palvelimesta passiiviseen palvelimeen ja takaisin yhteyden luomiseksi, kunnes

jompi kumpi näistä palvelimista vastaa. Tällä tavalla saadaan myös toteutettua luvun 8 vaa-

timusten kohta numero 11. Ajuri toteuttaa vaihdoksen aktiivisen ja passiivisen palvelimen

väliä funktion CheckRedundancy avulla, mikä näyttää tältä:

/// <summary>

/// If the client can’t be reached in the ping message

(default: 5 seconds),

/// the driver will attempt to switch to using

the alternative client.

/// </summary>

private async Task CheckForRedundancy()

{

if ( _reduClient != null)

{

Logger.Warn("Attempting redundancy switch!");

ProtoLibClient switchClient = null;

await _client.CloseAsync();

switchClient = _client;

_client = _reduClient;

40

_reduClient = switchClient;

string url = _baseUrl;

_baseUrl = _reduBaseUrl;

_reduBaseUrl = url;

try

{

await _client.ConnectAsync();

await DefaultDataPointQueries();

SubscribeToEvents();

}

catch

{

Logger.Error("Couldn’t connect to redundant server!

Attempting again in 5 seconds.");

}

}

}

Tällä funktiolla siis vaihdetaan aktiivista ja passiivista palvelinta virhetilanteessa. Tämän li-

säksi tarkkaillaan SCADA:n aktiivisen ja passiivisen palvelimen tilatietoja välittävää datapoint-

arvoa, jonka perusteella päätellään ottaako tämä kyseinen instanssi ajurista yhteyttä X-AID

-palvelimeen. Tämä funktio puolestaan näyttää tältä:

/ / / <summary>

/ / / S u b s c r i b e s t o redundancy d a t a p o i n t in SCADA and d i s c o n n e c t s o r

c o n n e c t s upon h o s t name change

/ / / </ summary>

p r i v a t e async Task Subscr ibeToRedundancy ( )

{

OaVar i an t s u b s c r i p t i o n V a l u e = n u l l ;

O a D pV a l u eS u b s c r i p t i o n V a l u e S u b s c r i p t i o n = n u l l ;

V a l u e S u b s c r i p t i o n =

41

_oaManager . P r o c e s s V a l u e s . C r e a t e D p V a l u e S u b s c r i p t i o n ( ) ;

V a l u e S u b s c r i p t i o n . AddDp ( " r e d u I n f o . ac t iveHos tName " ) ;

V a l u e S u b s c r i p t i o n . S ing leVa lueChanged += ( vcsende r , vce ) =>

{

s u b s c r i p t i o n V a l u e = vce . Value . DpValue ;

_hostName = s u b s c r i p t i o n V a l u e . T o S t r i n g ( ) ;

Task . Run ( async ( ) => {

i f ( _hostName . Eq ua l s ( Envi ronment . MachineName ) ) a w a i t

Connect ( ) ;

e l s e i f ( _ c l i e n t . A c t i v e ) a w a i t _ c l i e n t . CloseAsync ( ) ;

} ) . Wait ( ) ;

} ;

a w a i t V a l u e S u b s c r i p t i o n . S t a r t A s y n c ( ) ;

}

Tämä funktio yhdessä DriverManagerin sisäänrakennetun datapoint-käsittelyn avulla toteut-

taa aiemmin vaatimuksissa mainitun SCADA-järjestelmän kahdennuksen käsittelyn.

Tärkeää on huomata myös XaidEncoder ja XaidDecoder-luokat, jotka toteuttavat ProtoLib-

ohjelmistokirjaston rajapinnat. Nämä luokat tekevät varsinaisen työn viestien kääntämisessä:

XaidDecoder tulkitsee tavuja ja muuttaa niistä C#-olioita, XaidEncoder puolestaan kääntää

C#-olion sisällön tavuiksi. Tämä tarkoittaa, että nämä ovat varsinaisen protokollatoteutuk-

sen omaavat luokat. XaidEncoder ja XaidDecoder luokat toteuttavat luvussa 8 määriteltyjen

vaatimusten kohdan numero yksi.

Esimerkiksi kameran tilan tulkitsemista varten XaidDecoder omaa tämänkaltaisen funktion:

/ / / <summary>

/ / / C r e a t e s a s i n g l e camera s t a t e from t h e b y t e a r r a y .

/ / / </ summary>

/ / / <param name=" s e r v e r C o n f i g u r a t i o n s "> S e r v e r r e s p o n s e

v a l u e s < / param >

/ / / <param name=" s t a r t I n d e x "> Index t o s t a r t i n t e r p r e t i n g

42

from </ param >

/ / / <param name=" cameras "> L i s t o f Camera o b j e c t s f o r s t o r i n g t h e

r e c e i v e d d a t a . < / param >

/ / / < r e t u r n s >The c u r r e n t i n d e x in a r r a y . < / r e t u r n s >

p u b l i c i n t C r e a t e S i n g l e C a m e r a S t a t e ( b y t e [ ] s e r v e r C o n f i g u r a t i o n s ,

i n t s t a r t I n d e x , L i s t <Camera > cameras )

{

CameraS ta t e c a m e r a S t a t e = new CameraS t a t e ( Va lueObse rve r )

{

CameraId =

B i t C o n v e r t e r . ToUInt32 ( S p l i t B y t e A r r a y ( s e r v e r C o n f i g u r a t i o n s ,

s t a r t I n d e x , 4 ) , 0 ) ,

S e r v e r I d =

B i t C o n v e r t e r . ToUInt32 ( S p l i t B y t e A r r a y ( s e r v e r C o n f i g u r a t i o n s ,

s t a r t I n d e x += 4 , 4 ) , 0 ) ,

V i d e o S i g n a l = ( V i d e o S i g n a l )

B i t C o n v e r t e r . ToUInt16 ( S p l i t B y t e A r r a y ( s e r v e r C o n f i g u r a t i o n s ,

s t a r t I n d e x += 4 , 2 ) , 0 ) ,

V i d e o Q u a l i t y = s e r v e r C o n f i g u r a t i o n s [ s t a r t I n d e x += 2 ] ,

P r o c e s s i n g E r r o r = ( P r o c e s s i n g E r r o r )

s e r v e r C o n f i g u r a t i o n s [++ s t a r t I n d e x ] ,

Act iveAlarmCount =

B i t C o n v e r t e r . ToUInt16 ( S p l i t B y t e A r r a y ( s e r v e r C o n f i g u r a t i o n s ,

++ s t a r t I n d e x , 2 ) , 0 ) ,

A l a r m S t a t e L i s t = new L i s t < Ala rmSta t e > ( )

} ;

i n t a l a r m S t a t e L i s t L e n g t h =

B i t C o n v e r t e r . To In t32 ( S p l i t B y t e A r r a y ( s e r v e r C o n f i g u r a t i o n s ,

s t a r t I n d e x += 2 , 4 ) , 0 ) ;

s t a r t I n d e x += 4 ;

f o r ( i n t i = 0 ; i < a l a r m S t a t e L i s t L e n g t h ; i ++)

{

43

s t a r t I n d e x = C r e a t e A l a r m S t a t e ( s e r v e r C o n f i g u r a t i o n s ,

s t a r t I n d e x , c a m e r a S t a t e ) ;

}

i n t camIndex = cameras . F i n d I n d e x ( cam =>

cam . CameraId . Eq ua l s ( c a m e r a S t a t e . CameraId ) ) ;

i f ( camIndex . Eq ua l s (−1) ) cameras . Add ( new Camera ( Va lueObse rve r )

{ CameraS t a t e = c a m e r a S t a t e , CameraId =

c a m e r a S t a t e . CameraId } ) ;

e l s e cameras [ camIndex ] . CameraS ta t e = c a m e r a S t a t e ;

re turn s t a r t I n d e x ;

}

Tässä tapauksessa tällä funktiolla on kolme parametria: varsinaisen datan sisältävä tavutau-

lukko, numeerinen arvo joka ilmaisee mistä indeksistä tulkitseminen aloitetaan sekä lista

Camera-olioista joihin tulkittu data säilötään. Tavutaulukon arvojen tulkinta seuraa X-AID-

protokollan määritelmää. Tässä tapauksessa se esimerkiksi tarkoittaa, että jokainen kameran

tilan sisältävä tavutaulukko alkaa uint-tietotyypillä, joka sisältää kameran tunnisteen, eli se

on taulukon lukemisen aloittaessa neljä ensimmäistä solua taulukossa. Tämän jälkeen tulee

palvelimen tunniste ja niin edelleen.

XaidDecoder ja XaidEncoder toimivat käytännössä samalla periaatteella mutta päinvastoin

toisiinsa nähden: XaidDecoder vastaanottaa tavutaulukkoja ja täyttää sille parametrisoitu-

ja luokkarakenteita, kun XaidEncoder vastaanottaa näitä olioita ja muodostaa niiden ar-

voista protokollamääritelmän mukaisia tavutaulukkoja. Esitellyssä funktiossa myös huoma-

taan ensi luvussa käsiteltävän riippuvuuksien injektoinnin suunnnittelumallin soveltaminen

XaidDriverin kehityksessä, sillä jokaiselle CameraState-luokan oliolle injektoidaan Value-

Observer-olio konstruktorin yhteydessä.

44

8.2 XaidDriverin kehityksessä sovelletut suunnittelumallit

Kehitystyössä sovellettiin useita olio-ohjelmoinnin suunnittelumalleja. Tällä tavalla pyrit-

tiin toteuttamaan SOLID-periaatetta (SRP, OCP, LSP, ISP, DIP) (Martin 2002). SOLID-

periaatteen lisäksi koodin tuottamisessa on sovellettu DRY-periaatetta (Don’t repeat your-

self, älä toista itseäsi), eli itseään toistavan koodin kirjoittamisen sijasta muodostetaan ope-

raatioita suorittavia parametrisoituja geneerisiä funktioita ja silmukoita. SOLID-periaate tar-

kemmin eriteltynä on seuraavalainen:

1 . S i n g l e R e s p o n s i b i l i t y P r i n c i p l e (SDP) , e l i yhden v a s t u u n

p e r i a a t e

2 . Open / Closed p r i n c i p l e (OCP) , e l i a v o i n / s u l j e t t u −p e r i a a t e

3 . L i skov S u b s t i t i o n p r i n c i p l e ( LSP ) , e l i L i s k o v i n

k o r v a u s p e r i a a t e

4 . I n t e r f a c e S e g r e g a t i o n P r i n c i p l e ( ISP ) , e l i r a j a p i n t o j e n

e r o t t e l u −p e r i a a t e

5 . Dependency I n v e r s i o n P r i n c i p l e ( DIP ) , e l i r i i p p u v u u k s i e n

i n j e k t o i n n i n s u u n n i t t e l u m a l l i

Yhden vastuun periaate määrittää, että jokaisella rajapinnalla, luokalla tai oliolla pitää olla

vain yksin selkeä vastuualue. Tämän periaatteen on alunperin kehittänyt Robert C. Martin

hänen kirjassaan Principles, Patterns, and Practices of Agile Software Development (“Single

Responsibility Principle” 2018-12-10; Martin 2002). Luokkasuunnittelussa tämä otetaan huo-

mioon jakamalla eri toiminnallisuudet selkeästi eri luokkiin rajapintojen taakse. Martinin

mukaan on ongelma, jos kehittäjä pystyy keksimään useamman kuin yhden syyn muokata

jotakin luokkaa. Tällöin useimmiten on kyse luokasta, jonka pitäisi olla kaksi erillistä luok-

kaa. Tämän takia XaidDriverin eri toiminnot on jaettu erillisiin luokkiin kontekstin perus-

teella ja jokaista niistä käsitellään vain rajapintojen kautta. Tämän periaatteen seuraamisen

huomaa XaidDriverin rajapintojen määrässä ja niiden selkeissä toiminnallisissa osa-alueissa:

esimerkiksi JSON-olioiden luomiselle on oma luokka nimeltä JsonBuilder, jonka tehtävänä

on vain ja ainoastaan luoda asiaankuuluvia JSON-olioita.

45

Avoin/suljettu -periaate tarkoittaa, että ohjelmiston entiteettien pitäisi olla avoimia laajen-

nukselle, mutta suljettuja muutoksille (“Open-Closed Principle” 2018-12-10; Martin 1996).

Tämän periaatteen toteuttaminen voi vaikuttaa hiukan työläältä, mutta kansantajuisesti voisi

sanoa että kovakoodauksen välttäminen on tärkein osa tätä suunnittelumallia. Avoin/suljet-

tu -periaate siis tarkoittaa että suunnitellaan moduuleja, jotka eivät koskaan muutu (Martin

1996). Jokaisen metodin ja aliohjelman pitäisi toteuttaa toiminnallisuutensa niin geneerisesti

ja parametrisoituina, että kyseisiä funktioita ei enää alkuperäisen kirjoituksen jälkeen muo-

kata. Voidaan toki kirjoittaa uusia funktioita, jotka kutsuvat näitä aiempia funktioita, mutta

valmiit funktiot ja moduulit pysyvät samanlaisina. Tämän toteutumisen havaitsee esimerkik-

si X-AID viestejä lähettävässä luokassa. Jokainen tämän luokan dataa lähettävistä funktiois-

ta käyttää SendRequest-funktiota, antaen tälle funktiolle parametrina viestisisällön, viestin

tunnisteen, viestin pituuden ja viestin tyypin. Tämä geneerisesti toteutettu funktio näyttää

seuraavalta:

/ / / <summary>

/ / / Sends t h e r e q u e s t t o X−AID s e r v e r .

/ / / </ summary>

p r i v a t e async Task < o b j e c t > SendReques t ( Command commandType , o b j e c t

c o n t e n t , u s h o r t messageId , u i n t messageLength )

{

Xa idReques t r e q u e s t = new XaidReques t . X a i d R e q u e s t B u i l d e r ( )

. SetCommandType ( commandType )

. S e t R e q u e s t C o n t e n t ( c o n t e n t )

. Se tMessage Id ( messageId )

. Se tMessageLeng th ( messageLength )

. B u i l d ( ) ;

re turn a w a i t _ c l i e n t . SendReques tAsync ( r e q u e s t ) ;

}

Myös Liskovin korvausperiaate ottaa kantaa luokkasuunnitteluun. Tämän periaatteen mu-

kaan aliluokan olion pitäisi aina olla käsiteltävissä myös perimänsä luokan oliona (Leppä-

nen M. 2009), eli samat perusoperaatiot pystyy toteuttamaan jokaisella oliolla joka perii

46

ylemmän luokan, vaikka oliokohtaiset lisäominaisuudet voivatkin vaihdella. Helpoimpia ta-

poja huomata, että tämä periaate ei toteudu, on löytää koodista erilaisia "häntiä", eli esimer-

kiksi rajapinnan toteuttava aliluokka sisältää rajapintamääritelmän omaiset funktiot, mutta

näissä funktioissa ei tehdä mitään tai pahimmassa tapauksessa heitetään NotImplemente-

dExceptionia (“Liskov Substition Principle” 2018-12-10). Nämä hännät voivat myöhemmin

aiheuttaa laajaa vahinkoa ja ongelmia, varsinkin jatkuvassa käytössä olevassa ohjelmistos-

sa. Tämän suunnittelumallin toteutumisen huomaa esimerkiksi QueryableAlarms-luokasta.

Jokainen AlarmsState-olio omaa myös AlarmState-luokan perivän QueryableAlarm-luokan

attribuutissa LatestAlarm, joka omaa kaikki AlarmState-luokan ominaisuudet sekä URL-

osoitteet kuvan ja videotiedoston lataamiseen. Myös häntiä on vältelty XaidDriverin imple-

mentaatiossa: jokaisessa ohjelman funktiossa suoritetaan jotakin operaatioita. Turhia funk-

tioita ei siis kokonaisuuden kannalta ole olemassa.

Rajapintojen erottelu -periaate toteaa, että asiakkaiden ei pitäisi olla riippuvaisia metodeista,

joita ne eivät käytä (“Interface Segregation Principle” 2018-12-10; Martin 2002). Sovellus-

kehittäjien pitäisi suosia ohuita ja keskittyneitä yhtä toiminnallisuutta toteuttavia rajapinto-

ja, eikä laajoja useita ominaisuuksia omaavia rajapintoja. Esimerkiksi moniperintä on yksi

tavoista toteuttaa tätä periaatetta: jos jokin osa sovelluksesta tarvitsee useampia toiminnal-

lisuuksia rajapinnasta, mutta muut osat sovelluksesta tarvitsevat vain osaa tämän saman ra-

japinnan toiminnallisuuksista, on järkevämpää tehdä kaksi erillistä rajapintaa ja toteuttaa ne

molemmat moniperinnän avulla useampaa toimintoa vaativassa luokassa. Tämän periaatteen

toteutumisen huomaa esimerkiksi ajurin rajapintojen määrässä: erillisiä rajapintoja ohjelmis-

tossa on yhdeksän kappaletta, joista jokainen toteuttaa vain ja ainoastaan yhtä sovelluksen

operaatioiden osa-aluetta, kuten aiemmin mainittu JsonBuilder-luokka.

Riippuvuuksien inversio -suunnittelumalli määrittelee erillisten moduulien välisen kommu-

nikaation raamit. Korkean tason moduulien ei pitäisi omata riippuvuuksia alemman tason

moduuleihin, kummankin näistä pitäisi olla riippuvaisia abstraktioista. Näiden abstraktioi-

den ei pitäisi olla riippuvaisia yksityiskohdista, vaan yksityiskohtien pitäisi olla riippuvai-

sia abstraktioista (“Dependency Inversion Principle” 2018-12-10; “Dependency Inversion

vs Dependency Injection vs Inversion of Control vs Programming to Interfaces” 2018-12-

10). Useimmiten tämän suunnittelumallin toteuttaminen aloitetaan luomalla uusia rajapin-

47

toja, jotka tarjoavat mahdollisuuden luoda ylimääräisiä abstraktiotasoja toiminnallisuutta

kutsuvan luokan ja operaation toteuttavan luokan välille. Tämän suunnittelumallin toteutu-

misen huomaa esimerkiksi XaidDriverin Driver-Service-Interface-Resource toiminnallisesta

rakenteesta. Tätä voi havainnoillistaa esimerkiksi DatapointModifier-luokan avulla. Data-

pointModifer on resurssi, jota kutsutaan IDatapointModifer rajapinnan kautta, mitä kutsu-

taan DatapointCreatorService-luokan kautta. Kun SCADA:n datapointteja alustetaan ja luo-

daan, ajuri kutsuu DatapointCreatorService-luokan funktiota, joka palauttaa IDatapointMo-

difier rajapinnan funktion, jonka DatapointModifer toteuttaa. Tällä kolmen abstraktiotason

erottelutavalla minkä tahansa osa tästä ketjusta pystyy korvaamaan jollain toisella luokalla,

mutta toiminnallisuus pysyy samanlaisena. Seuraavassa esimerkissä esitellään datapointtien

luomisen toteuttava funktioketju XaidDriverin koodilla, tosin tästä koodista on karsittu pois

asian havainnoillistamisen kannalta irrelevantteja funktioita.

p u b l i c c l a s s D a t a p o i n t C r e a t o r S e r v i c e

{

p u b l i c I D a t a P o i n t M o d i f i e r D a t a P o i n t C r e a t o r { g e t ; s e t ; }

i n t e r n a l a sync Task C r e a t e X a i d D a t a p o i n t T y p e s ( OaManager

oaManager )

{

a w a i t D a t a P o i n t C r e a t o r . C r e a t e X a i d D a t a p o i n t T y p e s ( oaManager ) ;

}

}

p u b l i c i n t e r f a c e I D a t a P o i n t M o d i f i e r

{

Task C r e a t e X a i d D a t a p o i n t T y p e s ( OaManager oaManager ) ;

}

p u b l i c c l a s s D a t a p o i n t M o d i f i e r R e s o u r c e : I D a t a P o i n t M o d i f i e r

{

p u b l i c a sync Task C r e a t e X a i d D a t a p o i n t T y p e s ( OaManager oaManager )

{

48

Logger . I n f o ( " Xaid D a t a p o i n t c r e a t i o n i n i t i a l i z e d . " ) ;

a w a i t C r e a t e S e r v e r D a t a P o i n t T y p e ( oaManager ) ;

a w a i t Crea t eCameraDa taPo in tType ( oaManager ) ;

a w a i t C r e a t e X a i d S y s t e m D a t a P o i n t T y p e ( oaManager ) ;

}

}

Aiemmin mainittujen mallien lisäksi ohjelmiston kehityksessä sovellettiin riippuvuuksien

injektoinnin suunnittelumallia (Dependency Injection), eli riippuvuudet injektoidaan luok-

kaan sen alustuksen tapahtuessa. Tämän suunnittelumallin seuraamisen on huomattu hel-

pottavan ohjelmiston ylläpitoa (Razina ja Janzen 2007). XaidDriverissa tätä mallia sovelle-

taan paljon: XaidInputDriver toteuttaa räätälöidyn IXaidObserver-rajapinnan, joka sisältää

ModelValueChanged-funktion. Alustuessaan XaidInputDriver alustaa varsinaisen ajurin si-

sältävän XaidDriver-luokan ja injektoi siihen referenssin itseensä IXaidObserverin muodos-

sa. Tämän jälkeen XaidDriver jatkaa tämän referenssin injektiota syvemmälle ohjelmiston

kerroksissa. Lopulta alimmilla tasoilla olevat malli-luokat toteuttavat IXaidObservable raja-

pinnan. Tätä aihetta sivuttiinkin jo luvussa 8.1.

Riippuvuuksien injektoinnin avulla on toteutettu muuten ongelmia aiheuttava arvojen päi-

vitys spontaanista palvelin-tapahtumasta: useimmissa tapauksissa viestin lähetys ja proses-

sointi vaatisi viestin lähettämistä ja kutsun muodostamista sekä operaation seurauksena vas-

taanotetun XaidResponse-luokan tulkintaa. Riippuvuuden injektoinnin avulla XaidDecoder

omaa referenssin XaidInputDriveriin IXaidObserverin rajapinnan muodossa ja näin spontaa-

nin palvelinviestin tulkinnan yhteydessä voidaan laukaista IXaidObserver-rajapinnan Model-

ValueChanged-funktio ja antaa kyseiselle funktiolle parametrina muuttunut malli-luokka ja

sen tyyppi. Tämän jälkeen XaidInputDriver tulkitsee vastaanotetun olion sisällön ja tyypin,

kutsuen näiden tietojen perusteella XaidDriverin malleja päivittävää funktiota sekä asettaa

arvon valvomo-ohjelmistoon. Lienee syytä mainita, että switch-case ei toimi C#:n GetType()-

funktion kanssa, mistä syystä tämä rajoite on kierretty antamalla oikea tyyppi parametrina

ja switch-case-lauseessa tulkitaan tyypin nimeä. XaidInputDriverin sisältämä ModelValue-

Changed-funktio näyttää seuraavanlaiselta:

49

/ / / <summary>

/ / / F u n c t i o n t h a t t r i g g e r s when A l a r m S t a t e / CameraS ta t e / S e r v e r S t a t e

type of message i s r e c e i v e d

/ / / by t h e d e c o d e r .

/ / / </ summary>

p u b l i c a sync vo id ModelValueChanged ( I X a i d O b s e r v a b l e observedModel ,

Type type )

{

i f ( I n i t i a l C o n n e c t i o n D o n e )

{

Camera foundCam = n u l l ;

s w i t c h ( type . Name )

{

case " A l a r m S t a t e " :

A l a r m S t a t e a l a rm = ( A l a r m S t a t e ) observedModel ;

i f ( a l a rm . A l a r m s S t a t e . Eq ua l s ( A l a r m s S t a t e . A c t i v e ) )

{

D r i v e r . MapQueryableAlarm ( a la rm ) ;

D r i v e r . B e g i n R e c o r d i n g I n f o Q u e r y ( a l a rm ) ;

}

foundCam = D r i v e r . F indAndRep laceAla rmSta t e ( a l a rm ) ;

a w a i t Upda teCameraDa tapo in t ( foundCam ) ;

break ;

case " QueryableAlarm " :

foundCam = D r i v e r . Cameras . F ind ( cam =>

cam . CameraId . Eq ua l s ( ( ( QueryableAlarm ) observedModel ) . CameraId ) ) ;

i f ( foundCam != n u l l ) a w a i t

Upda teCameraDa tapo in t ( foundCam ) ;

break ;

case " CameraS t a t e " :

foundCam =

D r i v e r . F indAndRep laceCameraS ta t e ( ( CameraS ta t e ) observedModel ) ;

50

a w a i t Upda teCameraDa tapo in t ( foundCam ) ;

break ;

case " S e r v e r S t a t e " :

S e r v e r f o u n d S e r v e r =

D r i v e r . F i n d A n d R e p l a c e S e r v e r S t a t e ( ( S e r v e r S t a t e ) observedModel ) ;

a w a i t U p d a t e S e r v e r D a t a p o i n t ( f o u n d S e r v e r ) ;

break ;

case " X a i d P a r a m e t e r s " :

D r i v e r . S y s t e m P a r a m e t e r s . X a i d P a r a m e t e r s =

( X a i d P a r a m e t e r s ) observedModel ;

break ;

case " X a i d S y s t e m P a r a m e t e r s " :

a w a i t

U p d a t e S y s t e m D a t a p o i n t ( ( X a i d S y s t e m P a r a m e t e r s ) observedModel ) ;

break ;

}

}

}

Tarkempi XaidDriverin sisäinen rakenne on eritelty seuraavassa kuvassa - tämä kuva ei tosin

sisällä koko ohjelman kaikkia luokkia - vaan pyrkii mallintamaan pelkästään ajurin sisäisen

rakenteen olennaisimmat funktionaaliset luokat sekä datan säilytystä varten kehitetyt luokat.

51

Kuvio 7. XaidDriverin sisäinen rakenne52

Vasemmalla olevat funktionaaliset luokat koostuvat usean abstraktiotason takana sijaitsevista

resursseista, jotka tarjotaan ajurille rajapintojen kautta, joita käyttävät palvelut. Näin varsi-

naisen ajurin tarvitsee vain kutsua palveluluokkaa, joka omaa rajapinnan resurssiluokkaan,

jossa suoritetaan varsinaiset toiminnallisuudet. Service-luokan ja rajapinnan olemassaoloa

on kuvattu tässä kuvassa mustalla pallolla.

Kuvasta on myös rajattu pois osa luokista, joihin XaidDriverilla ei ole eksplisiittisiä viit-

tauksia. Näihin sisältyy esimerkiksi XaidDriverin käyttämät XaidEncoder ja XaidDecoder,

joiden kutsuminen tapahtuu ajurin yhteydessä alustetun ProtoLib-kirjaston toimesta. Ajuria

ohjaavat XaidInputDriver ja XaidOutputDriver, jotka toteuttavat DriverManagerin ajurialus-

tan input- ja output-rajapinnat. XaidInputDriver sisältyy kuvassa DriverManagerin kokonai-

suuteen, joka omaa referenssin XaidDriveriin. Nämä input- ja output-luokat omaavat yhtei-

sen XaidSingleton-luokan joka sisältää itse XaidDriverin. Tällä tavalla estetään useamman

instanssin syntyminen ja varmistetaan, että kummassa tahansa input- ja output-luokissa aju-

riin viitatessa kyse on samasta oliosta. Järkeviksi todettujen suunnittelumallien seuraaminen

yhdistettynä testivetoiseen kehitykseen vähentää virheiden määrää ja parantaa tuotetun oh-

jelmiston laatua.

53

8.3 Datan representaatiot WinCC OA:ssa

Useimmat XaidDriverin luokkaolioista sisältävät useamman TCP-kyselyn palauttamaa da-

taa, joka on sitten koostettu kantaluokkiin. Näitä kyselyitä ovat esimerkiksi palvelimen ja

kameroiden statukset, palvelimen ja kameroiden asetukset, hälytykset ynnä muuta sellais-

ta. Pääasialliset kantaluokat ovat Server ja Camera. Näitä edustaa SCADA:ssa datatyypit

IF_XaidCam ja IF_XaidServer. Jokaisella näiden tyyppien datapointeista on kaksi olen-

naista kenttää: controlValue- ja statusValue-kentät. StatusValue sisältää X-AID-palvelimelta

vastaanotetun kyseisen olion tilan. ControlValue-kenttää käytetään datan välittämiseen X-

AID-palvelimelle. Esimerkiksi jos kameran controlValue-kenttään ajetaan JSON-teksti, joka

käskee disabloimaan tämän kameran, poimii XaidDriver DriverManagerin kautta tämän tie-

don ja disabloi kameran, päivittäen tämän jälkeen statusValue-kenttään attribuutin disabled

arvoksi true. Tämän lisäksi WinCC OA sisältää myös kaksi muuta X-AID datapointtia:

IF_XaidSystem ja INT_XaidSetup.

INT_XaidSetup sisältää alustuksen yhteydessä tarvittavat arvot ja muut vastaavat asetukset.

Näihin sisältyy esimerkiksi CreateXaidDatapoint-arvo, jota XaidDriver kysyy alustuessaan.

INT_XaidSetup-datapointtiin sijoitetaan aiemmin luvussa 6 esitelty XaidDriverin konfiguraatio-

JSON. Mikäli arvo on tosi, poistetaan kaikki IF_XaidCam, IF_XaidServer ja IF_XaidSystem

datapointit sekä niiden datapointtien tyyppi-määritelmät. Tämän poiston jälkeen luodaan uu-

det mallit näille arvoille ja täytetään ne TCP-kyselyiden vastauksien palauttamilla arvoilla.

Suoritustehojen säästämiseksi alkuperäisen alustuksen jälkeen spontaaneiden tapahtumien

seurauksesta muuttuneiden luokkien tunnisteet kerätään talteen ja WinCC OA:n datan päivi-

tys tapahtuu sekunnin välein.

IF_XaidSystem puolestaan sisältää koko järjestelmän laajuista dataa: asetuksia videoiden ja

kuvien käsittelyyn, asetuksia hälytysten käsittelyyn yms. Tämän datapointin arvoja ei varsi-

naisesti välitetä PLC:lle, mutta se omaa useita datankäsittelyyn liittyviä asetuksia. Esimerk-

kirakenne XaidSystem-1 datapointin statusarvon sisällöstä on kehityksen yhteydessä simu-

laattorilta vastaanotetun datan mukainen:

{

"XaidParameters": {

54

"EmergencyLight": 90,

"SpeedThreshold": 60,

"DetectionTimeInSeconds": 90,

"MinimumVehicles": 100,

"AverageSpeed": 90,

"StatisticsInterval": 150

},

"ProcessingFilters": [],

"AlarmSettings": [

{

"AlarmType": 2,

"ObjectType": 0,

"ObjectId": 0,

"RecordingEnabled": -1,

"ContinuousRecording": -1,

"PreAlarmRecordTime": -1,

"PostAlarmRecordTime": -1

},

{

"AlarmType": 1,

"ObjectType": 0,

"ObjectId": 0,

"RecordingEnabled": -1,

"ContinuousRecording": -1,

"PreAlarmRecordTime": -1,

"PostAlarmRecordTime": -1

},

{

"AlarmType": 3,

"ObjectType": 0,

"ObjectId": 0,

55

"RecordingEnabled": -1,

"ContinuousRecording": -1,

"PreAlarmRecordTime": -1,

"PostAlarmRecordTime": -1

}

],

}

Tämä sisältää yleiset järjestelmäparametrit, prosessointifiltterit, hälytyksien tyyppikohtai-

set asetukset ja tilastodataa jokaiselta kaistalta. Datapointtien statusarvot sisältävät JSON-

muodossa kantaluokkiensa tämänhetkiset arvot. Varsinainen datan välitys tapahtuu Driver-

Managerin kautta ja data koostetaan JSON-muotoon ylikuormittamalla ToString()-metodi

dataa sisältävissä luokissa. Tämän avulla parsitaan arvoista räätälöityjä JSON-muotoisia tek-

sipätkiä, jotka sitten välitetään näihin datapointteihin. Esimerkiksi analysaattoripalvelimia

XaidDriverissa edustavan Server-luokan ylikuormitettu ToString()-metodi näyttää tältä:

p u b l i c o v e r r i d e s t r i n g T o S t r i n g ( )

{

i f ( S e r v e r C o n f i g != n u l l && _ s e r v e r S t a t e != n u l l )

{

re turn F o r m J s o n S t r i n g ( ) ;

}

e l s e re turn " " ;

}

p r i v a t e s t r i n g F o r m J s o n S t r i n g ( )

{

re turn J O b j e c t . FromObject ( new

{

S e r v e r I d ,

S e r v e r C o n f i g . Name ,

56

S e r v e r C o n f i g . CpuPower ,

S e r v e r C o n f i g . Address ,

_ s e r v e r S t a t e . S e r v e r S t a t u s ,

_ s e r v e r S t a t e . Usage ,

_ s e r v e r S t a t e . C a m e r a I d L i s t

} ) . T o S t r i n g ( F o r m a t t i n g . None ) ;

}

SCADA:a päivittäessä arvot haetaan etsimällä päivitettävä objekti tunnisteen perusteella,

minkä jälkeen luodaan päivitettävän datapointin nimi ja annetaan sille päivitettävän objektin

ToString()-funktion tulos. Tällä tavalla toteutetaan luvun 8 vaatimusten kohta numero 3.

Yksittäisen analysaattoripalvelimen sisältämä data WinCC OA:ssa näyttää tältä:

{

"ServerId": 1,

"Name": "X-AID-01",

"CpuPower": 1300,

"Address": "192.168.1.2:12345",

"ServerStatus": 1,

"Usage": 900,

"CameraIdList": [

9065,

9063,

9057,

9028,

9022,

9014,

9017,

9010,

9050

]

}

57

Esimerkiksi tämä palvelimen tunniste on 1, nimi on X-AID-01, prosessorin maksimiteho

on 1300, sen IP-osoite on 192.168.1.2 ja portti 12345, palvelin on toiminnassa koska sta-

tus on 1 ja varsinainen CPU:n käyttö on 900/1300. Lisäksi se sisältää sen hoitamien kame-

roiden tunnisteet listassa. Näiden kameroiden oma datapoint on taas tyyppiä IF_XaidCam.

IF_XaidCam datapointin päivitys tapahtuu aivan samalla tavalla kuin palvelimien ja yksit-

täisen kameran sisältämä data SCADA:ssa näyttää seuraavanlaiselta:

{

"CameraId": 9010,

"LaneId": 0,

"ServerId": 1,

"Name": "HKA10",

"StreamId": 600010,

"CpuUsage": 100,

"ProcessingError": 0,

"VideoQuality": 0,

"VideoSignal": 0,

"AlarmStateList": [{}]

"LaneStatistics": [],

"ActiveAlarmCount": []

}

Tämä sisältää kameran, kaistan,tilastoja eri kaistoilta, videostreamin ja palvelimen tunnis-

teen. Se sisältää myös tietoa videokuvan laadusta ja signaalista. Koska kehitystyön yhtey-

dessä simulaattori ei pysty palauttamaan liikennetilastoja näiden kohdalla on tyhjä JSON-

taulukko. Jokainen tämän kameran yksittäinen hälytys AlarmsStateList-oliossa puolestaan

näyttää tältä:

{

"CameraId": 9010,

"LaneId": 1,

"LogicalAreaId": 1,

"StateTime": "2018-12-25T11:37:45.0848301+02:00",

58

"AlarmTime": "2018-12-26T12:15:23.1925127+02:00",

"AlarmType": 1,

"ProcessingState": 1,

"AlarmsState": 0,

"RecordingList": null,

"LatestAlarm": {

"QueryUrl": "http://localhost:11180/xaid/api/video/getalarmrec?

camera=9010&alarmtime=131902929081636595&alarmtype=1&lane=1&

logicalarea=1",

"QuerySnapshotUrl": "http://localhost:11180/xaid/api/video/

snapshot?camera=9010&time=131902929081636595&type=1",

"VideoReady": true,

"CameraId": 9010,

"LaneId": 1,

"LogicalAreaId": 1,

"StateTime": "2018-12-25T11:37:45.0848301+02:00",

"AlarmTime": "2018-12-26T12:15:08.1636595+02:00",

"AlarmType": 1,

"ProcessingState": 1,

"AlarmsState": 1,

"RecordingList": null,

"LatestAlarm": null

}

Järjestelmä omaa yksittäisen hälytystila-olion jokaista mahdollista hälytystä kohden. Jos ka-

mera esimerkiksi tarkkailee kolmea kaistaa ja kolmea loogista aluetta sekä omaa kolmenlai-

sia hälytystyyppejä, on tämän kameran AlarmsState listassa

33 = 27 (8.1)

solua, eli 27 erilaista hälytysoliota. Tässä siis eritellään hälytyksen kameran tunniste, kaistan

ja loogisen alueen tunniste sekä hälytyksen tyyppi. Näitä hälytyksiä on varsin monta, sillä

jokainen looginen alue ja kaista omaavat oman versionsa jokaisesta mahdollisesta hälytys-

59

tyypistä. Hälytyksen tyyppiä edustaa koodissa seuravaanlainen enumeraatio:

p u b l i c enum AlarmType { S t o p p e d V e h i c l e = 1 , SlowVehic le , Wrongway }

JSON-teksti kertoo milloin hälytyksen alustus on tapahtunut (statetime) ja milloin hälytys on

viimeksi vaihtunut aktiivisesta inaktiiviseen tai toisinpäin. Itse hälytys sisältää myös oman

AlarmState-luokkansa perivän QueryableAlarm-olion nimeltään LatestAlarm. Tämä olio si-

sältää tiedot viime kerrasta, kun tämä hälytys oli aktiivinen sekä HTTP-osoitteet kuvankaap-

pauksen ja videotiedoston lataamiseen. AlarmsState kertoo onko hälytys aktiivinen vai inak-

tiivinen. Esimerkiksi tässä yhteydessä kanta-hälytys on inaktiivinen eli 0, kun taas viimeisin

aktiivinen versio tästä hälytyksestä omaa arvon 1. VideoReady-attribuutti puolestaan kertoo,

voiko videon ladata hälytykseen liittyvien URL-osoitteiden kautta. Hälytysoliota luodessa

arvo alustetaan epätodeksi ja muodostetaan relevantit URL-osoitteet hälytyksen sisältämästä

datasta. Kun tilanne päättyy ja hälytys muuttuu inaktiiviseksi, päivitetään VideoReady-arvo

todeksi. Tällä tavalla ilmaistaan, että kyseiseen hälytykseen liittyvän videotiedoston pystyy

nyt lataamaan.

Datalle luodaan CTRL-skripti WinCC OA-järjestelmään, joka reagoi joka kerta kun jonkin

näiden datapointtien arvo muuttuu. Tämä skripti parsii arvojen sisältämästä JSON-tekstistä

relevantit tiedot ja sijoittaa ne PLC-järjestelmän arvoja edustaviin vastaaviin WinCC OA:n

datapointteihin, joista arvo välitetään PLC-logiikalle, joka laukaisee tarpeen mukaisia se-

kvenssejä.

60

8.4 XaidDriverin datan käsittely WinCC OA:ssa

Kuten aiemmin luvussa 1 todettiin, C# taipuu kompleksisempiin operaatioihin helpommin

kuin CTRL-skriptikieli. Juuri tästä syystä ajuri on toteutettu WinCC OA -järjestelmään re-

kisteröitynä C#-laajennuksena, joka välittää näitä arvoja WinCC OA:n datapoint-rakenteiden

sisälle. On kuitenkin selvää, että pelkällä tällä datalla ei tehdä mitään. Sitä pitää tulkita ja vä-

littää eteenpäin.

WinCC OA -järjestelmään on jo erikseen määritelty IF_Xaid-alkuisten datapointtien lisäk-

si PLC-sekvensseille erilliset datapoint-rakenteet, joihin näiden JSON-tietojen sisältö pitää

sijoittaa. Tätä varten käytetään WinCC OA:n aiemmin mainittua prosessimanageria. Tälle

prosessimanagerille annetaan DriverManagerin ja muiden tehtävien lisäksi tehtäväksi käyn-

nistää X-AID arvoja sijoittava yksinkertainen CTRL-skripti, joka hoitaa arvojen sijoituksen.

Pähkinänkuoressa tämä skripti jää kuuntelemaan muutoksia IF_XaidCam, IF_XaidServer

ja IF_XaidSystem datapoint-tyyppien datapointteihin, parsii kyseisen datapointin arvosta

JSON-tekstin sisällön ja rakentaa sen tietosisällön perusteella datapoint-osoitteen, johon ky-

seinen arvo sijoitetaan. Ohessa karsittu esimerkki kyseenomaisesta skriptistä: tämä funktio

hoitaa kameran arvojen sijoitusta.

main() {

dyn_string cameras = dpNames("XaidCam-HKA*.statusValue");

for (int i=1; i <= dynlen(cameras); i++) {

dpConnect("mapXaidCamera", true, cameras[i]);

}

}

void mapXaidCamera(string dp1, string valueMappings)

{

dyn_string keys;

dyn_mixed values;

mapping singleCam = jsonDecode(valueMappings);

string val = dpNames(singleCam["Name"]);

strchange(val, 0, 8, "IO_");

61

val = val + ".control";

mapping valMap = mapCameraValues(singleCam, val);

for (int camLength = 0; camLength<mappinglen(valMap); camLength++) {

dynAppend(keys, mappingGetKey(valMap, camLength + 1));

dynAppend(values, mappingGetValue(valMap, camLength + 1));

}

dpSet(keys, values);

}

Tässä esimerkissä on jätetty pois räätälöidyn mapCameraValues-funktion sisältö, jossa vain

luodaan oikeanlainen mapping-tyypin olio (vrt. C# Dictionary), joka sisältää listan datapoint-

tien sijainnista sekä niihin sijoitettavat arvot.

Toteutus hoituu pääosin CTRL-kielen funktiolla dpConnect, joka ottaa parametrina arvon

muuttuessa kutsuttavan funktion, tiedon pyöritetäänkö skripti jo alustuksen aikana kertaal-

leen läpi sekä listan tarkkailtavista datapoint-rakenteista. Tässä yhteydessä datapointtien ni-

met kysellään dpNames-funktion avulla, joka hakee kaikki kyselyyn täsmäävät datapoint-

rakenteet. Tämän jälkeen käydään vain silmukassa läpi jokainen datapoint-rakenne ja raken-

netaan sen sisällöstä mapping-olio jsonDecode()-funktion avulla. Lopuksi luodun mapping-

olion arvojen perusteella luodaan lista osoitteista sekä lista arvoista, jotka annetaan CTRL-

skriptikielen sisäiselle dpSet-funktiolle, joka sijoittaa parametrisoidut arvot vastaaviin para-

metrisoituihin datapointteihin.

Muut WinCC OA:n skriptit ja asetukset tarkkailevat näitä sijoituspaikkoja ja samalla tavalla

niiden arvojen muuttuessa nämä arvot välitetään eteenpäin PLC-logiikalle sekä T-LOIK-

Ohjaussovittimelle. WinCC OA:n SCADA-järjestelmä toimii tällä tavalla näiden usean eri

komponentin risteämiskohtana, jossa välitetään ajurin X-AID-järjestelmältä vastaanottamat

tiedot eteenpäin.

Myös erilaisten hälytystyyppien ja yksittäisten kameran hälytysten käsittelyn disablointi on

62

mahdollista. Tämä on toteutettu aiemmin mainitun ajurin XaidOutputDriver-luokan kaut-

ta, joka näkyy kuviossa 6. Käytännössä SCADA:ssa sijaitseva yksittäisen kameran tai ko-

ko järjestelmän laajuista dataa käsittelevään datapointtiin ajetaan controlValue-muuttujaan

jokin parametri JSON-muodossa, jonka DriverManager välittää XaidDriverille. Tämän jäl-

keen XaidDriver parsii tästä tiedosta esimerkiksi tietyn kameran tunnisteen ja disabloi kaikki

kyseiseltä kameralta tulevat hälytykset. Tämä toteutetaan lähettämällä X-AID palvelimelle

binääriprotokollan määrittelyn mukainen suodatinviesti, joka kertoo ettei ajuri halua vastaa-

nottaa tämän kameran tunnisteen lähettämiä hälytystietoja. Näihin suodattimiin on mahdol-

lista parametrisoida useita eri kaistoja, hälytystyyppejä, loogisia alueita ja kameroita. Tällä

tavalla on toteutettu luvun 8 vaatimuslistan kohta numero 10, sillä näiden funktioiden avulla

voidaan helposti SCADA:n kautta disabloida toisen tunneliputken kaikki ennaltamääritellyt

hälytykset: esimerkiksi eräs suodatin estää ilmoituksien saapumisen kaikista kyseisen tunne-

lin kaistalla 2 tapahtuvista hidas ajoneuvo -hälytyksistä.

63

9 X-AID integraation testaaminen

Koska kyseinen ajuri on toteutettu testivetoisella kehityksellä, on testien määrä varsin suu-

ri. Testien rakentaminen aloitettiin luomalla jokaiselle X-AID protokollatotetuksen viestille

testit. Näiden testien sisältö oli pääasiassa testata XaidDriverin kykyä tulkata ja muodostaa

protokollatoteutuksen mukaisia viestejä ja täyttää XaidDriverin sisältämiä luokkarakentei-

ta vastaanotetulla datalla. Luvussa käydään läpi toteutuksen olennaisimmat integraatiotestit,

joissa testataan mm. että WinCC OA-järjestelmä vastaanottaa XaidDriverilta tietoa ja päivit-

tää datapointtien arvoja hälytyksen lauetessa.

X-AID-järjestelmään liittyen on myös konfiguroitu useita Jenkins-operaatioita. Jenkins on

automaattinen jatkuva-integraatio-ohjelmisto, jolle saa määriteltyä erilaisista tapahtumista

laukeavia skripti-putkia. X-AID-integraatioon liittyviä Jenkins-operaatioita on monta: yk-

si PLC-koodille, joka kääntää ja arkistoi uusimmat versiot koodista ja PLC-simulaattorilla

ajettavasta logiikkaohjelmasta, toinen WinCC OA:lle, joka ajaa integraatiotestejä WinCC

OA:n ja PLC:n välillä, kolmas T-LOIK-Ohjaussovittimelle, joka käynnistää testiympäristös-

sä PLC-simulaattorin sekä WinCC OA:n ja liittää nämä kiinni toisiinsa sekä ajaa T-LOIK- ja

WinCC OA:n välisiä integraatiotestejä. Viimeisenä on vielä erillinen XaidDriver-operaatio,

joka käynnistää WinCC OA:n ja X-AID simulaattorin sekä ajaa sitä vasten XaidDriverin ja

WinCC OA:n väliset testit sekä XaidDriverin yksikkötestit. Osa näistä operaatioista ajetaan

ajastetusti esimerkiksi kaksi kertaa viikossa, kun osa taas ajetaan aina kun Jenkins huomaa

operaatioon konfiguroidun kansiopolun saaneen uutta sisältöä versionhallinnassa.

Tämä määrä erilaisia operaatioita saattaa vaikuttaa hieman ylilyönniltä, mutta kuten aiemmin

todettiin, automaatiojärjestelmissä luotettavuus on erittäin tärkeää. Näiden erilaisten auto-

matisoitujen operaatioiden avulla ohjelmaa testataan säännöllisesti jokaisella tasolla: PLC:n

ja SCADA:n välinen dataketju testataan WinCC OA:n Jenkins operaatioissa, XaidDriverin

ja WinCC OA:n väli testataan XaidDriver-operaatiossa ja T-LOIK:n ja WinCC OA:n vä-

liset operaatiot T-LOIK-Ohjaussovittimen operaatiossa. Tämä minimoi mahdolliset virheet

ja ikävät yllätykset itse käyttöönotto-vaiheessa ja kenttätesteissä. Seuraavissa luvuissa kä-

sitellään pääasialliset XaidDriverin kannalta olennaiset testit ja SCADA:n sekä XaidDrive-

rin väliset integraatiotestit. XaidDriveria varten kehitettiin myös integraatiotestejä T-LOIK-

64

ohjaussovittimen ja WinCC OA:n välille, mutta näiden käsittely ohitetaan tämän pro gradun

yhteydessä.

9.1 XaidDriverin yksikkötestaus

Yksikkötestien muodostaminen aloitettiin identifioimalla protokollamääritelmän mukaiset

luokat ja luomalla testit dekooderille sekä enkooderille. Tämän jälkeen näitä testejä vasten

kehitettiin XaidEncoder ja XaidDecoder -luokat. Testien kehityksessä hyödynnettiin NUnit-

ohjelmistokehystä, joka on suunniteltu C#-koodin kattavaan ja helppoon testaamiseen. Esi-

merkiksi tältä näyttää kameroiden tiloja kyselevä testi:

p u b l i c a sync Task Shou ldGe tCameraS ta t e ( L i s t < u i n t > c a m e r a I d s = n u l l )

{

XaidResponse r e s u l t = n u l l ;

i f ( c a m e r a I d s != n u l l ) r e s u l t = ( XaidResponse ) a w a i t

_ x a i d D r i v e r . Ge tCameraS ta t e ( camera Ids , 1 ) ;

e l s e r e s u l t = ( XaidResponse ) a w a i t

_ x a i d D r i v e r . Ge tCameraS ta t e ( new L i s t < u i n t > ( ) , 1 ) ;

A s s e r t . NotNul l ( _ x a i d D r i v e r . _ c l i e n t ) ;

A s s e r t . NotNul l ( r e s u l t ) ;

A s s e r t . NotNul l ( r e s u l t . Q u e r y R e s u l t ) ;

A s s e r t . I s I n s t a n c e O f ( t y p e o f ( L i s t <Camera >) , r e s u l t . Q u e r y R e s u l t ) ;

A s s e r t . I s N o t N u l l ( ( ( L i s t <Camera >) r e s u l t . Q u e r y R e s u l t ) [ 0 ] . CameraS t a t e ) ;

A s s e r t . IsNotEmpty ( _ x a i d D r i v e r . Cameras ) ;

A s s e r t . I s N o t N u l l ( _ x a i d D r i v e r . Cameras [ 0 ] . CameraS t a t e ) ;

}

Samankaltaiset testit on kirjoitettu jokaiselle kuudestatoista mahdollisesta TCP-kyselystä.

Joillain näistä on vielä useampia testejä, joissa haetaan esimerkiksi vain yksi kameran ti-

la, eikä kaikkia kameroiden tiloja. Ohessa myös varmistetaan että näiden kyselyiden arvot

tallennetaan XaidDriver-luokan attribuutteihin. Tämä testiluokka sisältää myös testit, joissa

simuloidaan X-AID-palvelimen kaatumista, yksittäisen analysaattoripalvelimen kaatumista

65

ja muita virhetilanteita.

Nämä testit testaavat lähinnä kuviossa 6 esiteltyjen luokkien välisten operaatioiden toimimis-

ta toivotulla tavalla. Kehityksen yhteydessä näiden testien läpäisy varmistettiin ennen koodin

lähettämistä versionhallintaan. Tämän jälkeen Jenkins-ohjelmisto ajoi automaattisesti nämä

testit vielä kertaalleen läpi ja julkaisi NUnit-testiraportin. Kattavien testien suunnittelun an-

siosta koodin refaktorointi myöhemmissä kehityksen vaiheissa oli melko vaivatonta, sillä

muutoksien jälkeen testien ajaminen auttoi huomaamaan mahdollisia epäkohtia ja helponsi

laadunhallintaa.

9.2 Integraatiotestaus XaidDriverin ja WinCC OA:n välillä

Jotta pystyttiin varmistamaan että XaidDriverin vastaanottama data kulkee WinCC OA:n as-

ti, testeihin injektoitiin WinCC OA:n C#-API, eli kuvassa 6 esitetty Oa C#-Manager. Tämän

avulla testeissä pystyi hakemaan WinCC OA:han välitettyä dataa antamalla datapointin ni-

men ja toivotun datan polun. Käytännössä tällainen operaatio näyttää seuraavanlaiselta:

s t r i n g j s o n =

oaManager . P r o c e s s V a l u e s . GetDpValue ( "HKA10 . s t a t u s V a l u e " ) . DpValue ;

C#-Manager omaa myös samanlaiset funktiot arvojen asettamiseen - mutta kuten aiemmin

mainittiin - näitä toimintoja ei kutsuta XaidDriverin sisällä alkuperäisten datarakenteiden

luomisen lisäksi, sillä itse DriverManager omaa funktiot arvojen sijoittamiseen WinCC OA-

järjestelmään ja nämä funktiot omaavat erilaisia varmistuksia, kuten järjestelmän kahden-

nuksen hallitsemisen. Integraatiotestien yhteydessä tämän API:n suora käyttö tosin helpottaa

datan kulun varmistamista.

Käytännössä jokainen WinCC OA:n ja XaidDriverin integraatiotesti on erilainen variaatio

samasta ajatuksesta:

1 . Käynnistetään WinCC OA -projekti ja DriverManager sekä alustetaan XaidDriver.

2 . Odotetaan, että XaidDriver on muodostanut yhteyden WinCC OA-järjestelmään ja

66

luonut tarvitsemansa datapointit.

3 . Haetaan jonkin datapointin arvo string-muuttujaan.

4 . Käynnistetään jokin spontaani palvelintapahtuma X-AID simulaattorissa suorittamalla

HTTP-rajapinnan yli simuloitu hälytystapahtuma.

5 . Odotetaan muutama sekuntti ja haetaan nykyinen saman datapointin arvo

string-muuttujaan.

6 . Verrataan näitä tekstiarvoja ja todetaan, että simuloidun hälytyksen arvo on päivittynyt

eteenpäin.

7 . Deaktivoidaan hälytys ja varmistetaan että arvo vastaa oletettua.

Tämän tarkemmaksi havainnoillistamiseksi esimerkkinä kameran HKA10 hälytyksiä testaa-

va yksinkertainen testi:

[ Tes t , R e t r y ( 2 ) ]

p u b l i c a sync Task Ala rmCoun tAndAla rmSta t eUpda teMul t ip l e ( )

{

a w a i t _ x a i d I n p u t D r i v e r . D r i v e r . D e f a u l t D a t a P o i n t Q u e r i e s ( ) ;

_ x a i d I n p u t D r i v e r . I n i t i a l C o n n e c t i o n D o n e = t rue ;

LogResponse ( a w a i t S i m A c t i v a t o r . GetAsync ( L o c a l H t t p +

_ i n c i d e n t D e a c t i v a t i o n S i m U r l s [ 0 ] ) ) ;

a w a i t S i m A c t i v a t o r . GetAsync ( L o c a l H t t p +

_ i n c i d e n t D e a c t i v a t i o n S i m U r l s [ 1 ] ) ;

a w a i t S i m A c t i v a t o r . GetAsync ( L o c a l H t t p +

_ i n c i d e n t D e a c t i v a t i o n S i m U r l s [ 2 ] ) ;

a w a i t Task . Delay ( 5 0 0 0 ) ;

OaManager oaManager = _ x a i d I n p u t D r i v e r . OaManager ;

s t r i n g o r i g i n a l J s o n = oaManager . P r o c e s s V a l u e s

. GetDpValue ( " XaidCam−HKA10 . s t a t u s V a l u e " ) . DpValue ;

a w a i t S i m A c t i v a t o r . GetAsync ( L o c a l H t t p +

_ i n c i d e n t A c t i v a t i o n S i m U r l s [ 0 ] ) ;

67

a w a i t S i m A c t i v a t o r . GetAsync ( L o c a l H t t p +

_ i n c i d e n t A c t i v a t i o n S i m U r l s [ 1 ] ) ;

a w a i t S i m A c t i v a t o r . GetAsync ( L o c a l H t t p +

_ i n c i d e n t A c t i v a t i o n S i m U r l s [ 2 ] ) ;

a w a i t Task . Delay ( 5 0 0 0 ) ;

s t r i n g r e c e n t J s o n = oaManager . P r o c e s s V a l u e s

. GetDpValue ( " XaidCam−HKA10 . s t a t u s V a l u e " ) . DpValue ;

A s s e r t . I s F a l s e ( o r i g i n a l J s o n . E qu a l s ( r e c e n t J s o n ) ) ;

J O b j e c t o r i g i n a l = J O b j e c t . P a r s e ( o r i g i n a l J s o n ) ;

J O b j e c t s e c o n d a r y = J O b j e c t . P a r s e ( r e c e n t J s o n ) ;

A s s e r t . AreNotEqual ( o r i g i n a l [ " Act iveAlarmCount " ] ,

s e c o n d a r y [ " Act iveAlarmCount " ] ) ;

a w a i t S i m A c t i v a t o r . GetAsync ( L o c a l H t t p +

_ i n c i d e n t D e a c t i v a t i o n S i m U r l s [ 0 ] ) ;

a w a i t S i m A c t i v a t o r . GetAsync ( L o c a l H t t p +

_ i n c i d e n t D e a c t i v a t i o n S i m U r l s [ 1 ] ) ;

a w a i t S i m A c t i v a t o r . GetAsync ( L o c a l H t t p +

_ i n c i d e n t D e a c t i v a t i o n S i m U r l s [ 2 ] ) ;

a w a i t Task . Delay ( 5 0 0 0 ) ;

r e c e n t J s o n = oaManager . P r o c e s s V a l u e s

. GetDpValue ( " XaidCam−HKA10 . s t a t u s V a l u e " ) . DpValue ;

o r i g i n a l = J O b j e c t . P a r s e ( o r i g i n a l J s o n ) ;

s e c o n d a r y = J O b j e c t . P a r s e ( r e c e n t J s o n ) ;

A s s e r t . AreEqual ( o r i g i n a l [ " Act iveAlarmCount " ] ,

s e c o n d a r y [ " Act iveAlarmCount " ] ) ;

}

Testi siis toimii juuri aiemman listan tavalla. Se hakee dataa, simuloi hälytyksiä ja noutaa

WinCC OA:sta JSON-muotoisia tekstipätkiä, parsii niistä C#:n NewtonSoft JSON-kirjaston

JObject-olion ja vertailee vastaanotettuja arvoja. Näitä testejä on tietenkin useampia ja useam-

68

malle kameralle, palvelin- ja tilastodatalle ja niin edelleen, mutta kaikki niistä seuraavat sa-

maa periaatetta.

Järjestelmien kahdennuksen testaaminen puolestaan toteutettiin kahdella identtisellä WinCC

OA-instanssilla. Toinen näistä instansseista sijaitsi virtuaalikoneella, toinen varsinaisella työ-

asemalla. Tämän lisäksi simulaattoreja oli kaksi, kummatkin konfiguroituna eri portteihin.

Tällä tavalla pystyi simuloimaan sekä SCADA:n aktiivisen ja passiivisen palvelimen vaih-

tumista, sekä X-AID-palvelimen kahdennusta. Tämä tapahtui vaihtamalla SCADA:n ak-

tiivista osapuolta summittaisesti ja aiheuttamalla keinotekoisia yhteysongelmia näiden eri

simulaattori-instanssien välillä. Jos ajatellaan, että X-AID-simulaattori 1 ja 2 ovat nimellä

X1 ja X2, kun taas SCADA-instanssit nimellä S1 ja S2, näiden testien esimerkkikulku on

seuraavanlainen:

1 . Alustetaan S1, S2, X1 ja X3.

2 . Asetetaan S1 ja X1 aktiivisiksi osapuoliksi ja varmistetaan kommunikaation toiminen

sekä simuloidaan erilaisia tilanteita.

3 . Kaadetaan X1 ja varmistetaan, että S1 osaa automaattisesti yhdistyä X2:seen sekä

simuloidaan erilaisia tilanteita..

4 . Asetetaan S1 passiviseksi ja S2 aktiiviseksi, varmistaen että S2 osaa initialisoida

yhteyden X2:seen sekä simuloidaan erilaisia tilanteita.

5 . Toistetaan kohtia 1-4 erilaisilla variaatioilla, kunnes kahdennuksen toimivuus todetaan

riittäväksi.

X-AID-palvelimet ovat järjestelmän toimittajan mukaan jatkuvasti synkronisoituja ja omaa-

vat yhteisen tietokannan, joten näiden yhteinen synkronisuus ei kuulunut tämän suunnittelu-

tutkimuksen piiriin.

Ohjelmaa testattiin mahdollisia muistivuotoja vastaan jättämällä WinCC OA:n projekti pyö-

rimään testiympäristöön viikonlopun yli XaidDriverin ollessa päällä, samalla kun ikuisessa

silmukassa pyörivällä powershell-skriptillä simuloitiin erilaisia hälytyksiä ja virhetilanteita.

Simulaatioon luotiin satunnaisuutta soveltamalla varsin paljon powershellin Get-Random()-

funktiota. Käytännössä skriptin ansiosta oli satunnaista minkä tyyppinen virhetilanne tai hä-

69

lytysmassa tapahtui, kuinka kauan tilanteet kestivät ja kuinka kauan kesti ennen kuin seuraa-

va kierros tästä silmukasta alkoi. Viikonlopun jälkeen tarkistettiin muistin kulutus ja verrat-

tiin sitä alkutilanteeseen.

Muistivuotojen tarkkailu oli erittäin tärkeää, sillä C# omaa automaattisen roskienkeruun ja

muistinvapautuksen, mutta tähän ei voi täysin luottaa. Ottaen huomioon, että kyseinen so-

vellus tulee olemaan päällä vuorokauden ympäri, voivat nämä muistivuodot aiheuttaa suuria

ongelmia liikenteenhallintajärjestelmissä. Tietenkään tämä ei ole täydellinen tapa löytää näi-

tä mahdollisia muistivuotoja, mutta se antaa suuntaa mahdollisista ongelmista. Testaamisella

pyrittiin varmistamaan, että luvun 8 vaatimusten kohta numero 9 täyttyy.

Testi suoritettiin kahdesti, kahtena eri viikonloppuna. Ensimmäisenä viikonloppuna havait-

tiin taustalle elämään jäänyt Timer-luokan olio, joka aiheutti noin 30 megatavun muistivuo-

don 24 tuntia kohden. Koodiin lisättiin yksi rivi ja muistivuoto poistui. Toisella testikerralla

puolestaan havaittiin, että järkevien suunnittelumallien ja huolellisen testaamisen seurauk-

sena ei löytynyt muistivuotoja tai ennaltaodottamattomia ongelmia. Aiemmalla testikerralla

löytynyt lievä muistivuoto jäi siis ainoaksi laatuaan.

9.3 Kenttätestien huomioita ja tuloksia

Alustavat kenttätestit X-AID integraatiolle alkoivat heti varsin positiivisella tavalla, sillä

ajurin asennus toimi juuri kuten pitikin: muutamaa nappia painamalla XaidDriver asentui

osaksi SCADA-järjestelmää, käynnistyi ilman ongelmia ja otti yhteyden oikeaan X-AID-

järjestelmään. Tämän jälkeen ajuri automaattisesti loi tarvittavat datapointit SCADA-järjestelmään

ja täytti ne palvelimelta vastaanotetun datan JSON-representaatioilla. Sen jälkeen ajuri ru-

pesi toimimaan juuri kuten se oli suunniteltu: ajuri alkoi välittämään hälytyksiä ja muita

X-AID järjestelmältä vastaanotettuja spontaaneista tapahtumista tulkittuja tietoja SCADA-

järjestelmän datapointteihin.

Täysin ongelmitta ohjelma ei kuitenkaan lähtenyt toimimaan. X-AID-järjestelmän toimitta-

ja oli luokitellut aiemmin mainitut loogiset alueet palo-aluiden perusteella (1-7), kun taas

YSP:n tuottamat sekvenssit luokittelivat loogiset alueet kamerakohtaisesti väliltä 1-3. Nämä

alueet oli laskettu kameran etäisyydestä johonkin paloalueeseen, eli PLC-laitteiston näkö-

70

kulmasta jollakin kameralla, joka esimerkiksi tarkkaili paloalueita 3, 4 ja 5, nämä alueet oli

luokiteltu alueiksi 1, 2 ja 3. Tämä vaati muutoksia SCADA:ssa sijaitsevaan CTRL-skriptiin,

joka välitti tietoa PLC-laitteistolle. Käytännössä kameran tunnisteen perusteella piti tulkita,

oliko palvelimelta vastaanotettu arvo looginen alue 1, 2 vai 3. Tämä onneksi oli melko yksin-

kertaista korjata, sillä piti vain tehdä yksi uusi funktio, joka kameran tunnisteen perusteella

konvertoi esimerkiksi vastaanotetun alueen 7 alueeksi 1 PLC-laitteistolle.

Kaikki ongelmat eivät kuitenkaan ratkenneet pelkästään tällä korjauksella: oikean järjestel-

män lähettämän datan määrä oli paljon simulaatioita suurempaa. Tämä nosti esiin selkeän

ongelman XaidDriverin vastaanottamien datojen käsittelyssä: DatapointModifer-luokassa oli

selvä suunnitteluvirhe. C#:n LINQ-operaatioita oli sovellettu varsin paljon datan asettami-

sessa. Ongelmana oli lähinnä C#:n .ForEach-lambda ja .FindIndex-lambda, sillä koko sovel-

lus oli suunniteltu asynkrooniseksi. Kyseiset funktiot aiheuttivat poikkeuksia, sillä jos tämän-

kaltaisen listan solujen läpikäymisen yhteydessä listaan lisättiin tai sieltä poistettiin materi-

aalia, meni ohjelma siitä sekaisin. XaidDriver omasi päälläollessaan keskimäärin noin 40 eri

säiettä, joista jokainen suoritti asynkronisesti omia operaatioitaan. Samoja listoja muokattiin

useassa eri säikeessä samanaikaisesti.

Ongelman olisi voinut ratkaista lukoilla, mutta nopeamman datan välityksen vuoksi ongelma

korjattiin seuraavalla tavalla: jokaisessa aliohjelmassa vain kopioitiin alkuperäinen paramet-

risoitu lista toiseen listaan, jossa suoritettiin nämä operaatiot ja operaatioiden tulokset asetet-

tiin varsinaisiin olioihin. Koska ohjelma päivitti muuttuneita arvoja SCADA-järjestelmään

sekunnin välein, joka tapauksessa seuraavan sekunnin syklin aikana aiemman datan käsit-

telyn aikana tapahtuneet ja poisjääneet muutokset päätyivät miltei reaaliajassa valvomo-

ohjelmiston datarakenteisiin.

Näiden ongelmien korjaamisen jälkeen ajuri rupesi toimimaan juuri toivotulla tavalla: sil-

lä hetkellä yhteydessä ja toiminnassa olevat kamerat, jotka havaitsivat hälytyksiä, alkoivat

välittämään dataa aivan oikealla tavalla ja laukaisemaan sekvenssejä sekä ilmaisemaan käyt-

töliittymän kautta, että näin oli tapahtunut.

71

10 Yhteenveto ja jatkotoimenpiteet

Tässä pro gradussa esiteltiin YSP Oy:n Liikeennevirastolle tuottamien liikenteenhallintajär-

jestelmien arkkitehtuurinen rakenne ja esiteltiin tapa integroida erillinen järjestelmä osaksi

tätä kokonaisuutta. Lopputuotoksena syntyi valvomo-ohjelmistoon ajuri, jonka avulla ohjel-

misto pystyy ottamaan vastaan dataa tältä erilliseltä järjestelmältä. Samalla eriteltiin erilaisia

järkeviä suunnittelumalleja joita soveltamalla varmistettiin, että koodin laatu pysyi hyvänä

sekä esiteltiin pääpiirteissään erilaisia tapoja testata kyseisen ajurin toimivuutta.

Pro gradussa käsiteltiin XaidDriver-nimisen protokollatulkin kehitystä ja avattiin sen toi-

mintaan liittyviä erillisiä komponentteja. Näitä komponentteja ovat PLC, SCADA ja REST-

sovellukset. PLC kappaleessa esiteltiin ohjelmoitavien logiikoiden toiminta, niitä ohjaava

kieli (Structured Text) ja niiden liittäminen SCADA-ohjelmistoon. SCADA-luvussa käsitel-

tiin SCADA-ohjelmiston rakenne, taustalla oleva ajatus ja XaidDriverin kanssa sovelletta-

vaa SCADA-ohjelmistoa, eli Siemensin WinCC OA:ta. WinCC OA:n käsittelyn yhteydes-

sä avattiin mahdollisia tapoja liittää korkean tason ohjelmointikielten tarjoamia komplek-

sisempia operaatiota WinCC OA:n CTRL-skriptikieleen. Tämän jälkeen käsiteltiin REST-

arkkitehtuuria sekä T-LOIK-Ohjaussovitinta, jonka avulla SCADA-järjestelmä liitetään laa-

jempaan suomenlaajuiseen T-LOIK sovellukseen.

Lopuksi käsiteltiin pro gradun tuloksena syntyneen XaidDriverin rakenne, sen kehityksessä

sovelletut suunnittelumallit sekä sen testaaminen. Käsiteltyjä suunnittelumalleja olivat muun

muassa SOLID-periaate sekä riippuvuuksien injektio. Tämän pro gradun yhteydessä tarjot-

tiin uutta tietoa Suomen liikennejärjestelmien toiminnasta: tästä aiheesta ei juurikaan ole tie-

dettä saatavilla, sillä tällaisia ratkaisuja tarjoavia yrityksiä on Suomessa vain muutama, jois-

ta mikään ei ole juurikaan julkaissut tieteellisiä artikkeleja. Tutkielma tarjoaa näkökulmaa

automaatiosuunnittelun maailmaan ohjelmistosuunnittelijan näkökulmasta.

Suunnitteluprosessi seurasi Hevnerin ja Chatterjeen (2010) määrittelemiä suunnittelututki-

muksen syklejä: relevanssisykliä, suunnittelusykliä sekä täsmällisyyssykliä. Relevanssisyklis-

sä kartoitettiin olemassaolevat kirjastot, teknologiat, vaatimukset ja ympäristö, mitä ohjel-

miston kehityksessä sovellettiin sekä suunniteltiin toteutusta ja ohjelmiston rakennetta. Suun-

72

nittelusyklinä toimi ajurin kehitys ja eri komponenttien yhteensovittaminen. Täsmällisyys-

syklinä puolestaan toimi ohjelman jatkuva testaaminen sekä lopputulokset. Näitä syklejä

toistettiin useita kertoja ja tuloksia hiottiin ajan kuluessa, kunnes ajuri saavutti toivotun toi-

mivuustason ja täytti sille asetetut kohdassa 8 määritellyt vaatimukset.

Toteutettu ajuri on nopeampi kuin perinteinen REST-palvelu. Data kulkee binääriprotokol-

lan kautta, minkä seurauksena yksittäinen viesti on erittäin pieni, pienimmillään vain 16 ta-

vua. Tätä kun vertaa REST-palveluun, jossa viestejä välitetään XML- tai JSON-muodossa,

on datan koko pienempi ja operaatiot ovat nopeampia. Syntynyt ajuri on myös reaaliaikai-

nen: hälytyksen lauetessa viimeistään sekuntti hälytystilanteen alkamisen jälkeen tieto hä-

lytystilanteesta ja kuva tilanteen alkamisesta on toimitettu SCADA-järjestelmään. Tilanteen

päättyessä tai parametrisoidun aikavälin päättyessä myös videotiedosto on saatavilla. Eli jos

vaikkapa laukeaa väärään suuntaan ajavan ajoneuvon hälytys, joka kestää 30 sekunttia, on

valvomossa viimeistään 35 sekunnin päästä tilanteen alkamisesta ladattavissa videotiedosto

kyseisestä hälytystilanteesta. Tämäntasoinen reaaliaikaisuus mahdollistaa nopean reagoinnin

vaaratilanteissa ja parantaa liikenteen turvallisuutta tunnelissa.

Simulaattoria vasten ajurilla kesti 59 millisekunttia hakea 38 eri kameran 27 eri mahdol-

lista hälytystä ja muodostaa niistä C#-representaatiot. Käytännössä näiden 59 millisekun-

nin aikana täytettiin ja sijoitettiin tietorakenteisiin 1026 luokkaa, joista jokaiselle täytet-

tiin 8 eri kenttää. Tämän tasoinen reaaliaikaisuus olisi huomattavasti vaikeampaa toteuttaa

REST-sovelluksella, sillä XML:n ja JSON:in käsittelyssä ja tulkinnassa kestää pidempään

kuin yksinkertaisen tavutaulukon lukemisessa, kuten myös itse viestin kulussa, sillä TCP on

huomattavasti matalamman tason protokolla kuin HTTP. Tutkielman ohessa myös sivuuttiin

ProtoLib-kirjastoa, jonka avulla tämänkaltaisten protokollatulkkien toteutus on helpompaa.

Tulosten perusteella voi kysyä, miksi tämänkaltaiset räätälöidyt binääriprotokollat eivät ole

vielä nykyistä yleisemmässä käytössä internetin välityksellä kommunikoivissa järjestelmis-

sä. Selvästi ne ovat suoritusteholtaan parempia ja nopeampia. Kyse varmaan lieneekin sii-

tä, että yksinkertaisen REST-sovelluksen kehittäminen on huomattavasti helpompaa, kuin

tämänkaltaisen binääriprotokollan. Tästä syystä sovellukset, jotka eivät tarvitse reaaliaikai-

suutta samalla tasolla kuin esimerkiksi liikenteenhallintajärjestelmä, voivat hyvin toimia hi-

taammalla ja raskaammalla HTTP:n yli kommunikoivilla REST-rajapinnoilla. Tämän pro-

73

tokollan toteutus onnistui silti varsin helposti, sillä protokollakäsittelyjä varten kehitetty

ProtoLib-ohjelmistokirjasto tarjosi suurta apua tähän prosessiin.

Tutkielman esittämä tapa tulkita binääriprotokollaa TCP-virrasta on myös yleistettävissä.

Periaatteessa jokainen internetin kautta kommunikoiva peli käyttää samantapaista toteutus-

ta, sillä esimerkiksi kameran ja hälytysten tietojen sijasta samankaltaisen protokollan sisällä

voi kulkea vaikkapa hahmon tunniste ja kordinaatit, joihin hahmo on liikkumassa. Tämä tar-

koittaa, että tutkielmassa esitettyjä suunnittelumalleja ja testivetoista kehitystä voi ja kannat-

taa soveltaa myös pelisuunnittelussa, mikäli peli kommunikoi verkon yli jonkin palvelimen

kanssa.

Testivetoisen kehityksen edut nousivat esille työn tuloksessa: huolellisen integraatiotestaa-

misen, automaatiotestaamisen ja yksikkötestaamisen tuloksena XaidDriverin asentaminen

tuotantopalvelimelle tapahtui kivuttomasti: samantien asennuksen jälkeen ohjelma otti yh-

teyden oikeaan X-AID-palvelimeen ja täytti WinCC OA:n datapointit palvelimelta haetuista

arvoista muodostetuilla JSON-olioilla ja alkoi välittämään hälytyksiä. Vaikka ajurin toimin-

nassa ilmenikin pieniä ongelmia, joita käsiteltiin aiemmassa kappaleessa, toimi ajuri pää-

piirteissään aivan suunnittelulla tavalla. Tämä vain vahvistaa luvussa 7.3 mainittujen IBM:n

sekä Georgen ja Williamsin tutkimuksissa havaittuja huomioita: testivetoisella kehityksellä

toteutetun koodin laatu ja luotettavuus on parempaa.

Sovelluksen toimintaa testataan myös kenttätesteissä. Näiden testien aikana SCADA-järjestel-

mää testataan paikan päällä. Tälle on varattu aikaa noin puoli vuotta, sillä kyseessä on varsin

monimutkainen järjestelmä. Tähän puoleen vuoteen tosin kuuluvat kaikki muutkin järjes-

telmään kuuluvat toiminnallisuudet, eikä pelkästään tutkielmassa käsitelty X-AID. Toden-

näköisesti tämän kattavan testauksen yhteydessä tulee varmasti esille joitain puutteita tai

ongelmia. Joka tapauksessa varsin laajalla testaamisella kehityksen yhteydessä näiden mah-

dollisten ongelmien määrä on pyritty minimoimaan.

Tämänkaltainen integraatioprojekti luonnollisesti vaatii laajamittaista testausta myös oikean

elämän tilanteissa ja todellisessa maailmassa. Ilman kenttätestausta olisi milten mahdotonta

kehittää näin suuria järjestelmiä. Tutkielma tarjoaa myös näkökulmaa siihen, kuinka laajo-

jen kokonaisuuksien kanssa ohjemistoalalla joutuu työskentelemään. Ero akateemisen maa-

74

ilman hallittuihin ja kompakteihin järjestelmiin on melkoinen ja mittakaava huomattavasti

suurempi.

Järjestelmää ei ole parin päivän mittaisen muistivuototestin lisäksi testattu jatkuvalla syö-

töllä, joten paikan päällä sen ollessa päällä vuorokauden ympäri useamman viikon putkeen

saattaa ilmetä joitain korjausta vaativia ongelmia. Onneksi juuri tämänkaltaisten syiden takia

järjestelmien testaamiseen on varattu aikaa. Kun kenttätesteissä ilmenneet puutteet ja virheet

on korjattu, siirrytään järjestelmän ylläpitoon.

75

Lähteet

Beck, Kent. 2003. Test-driven development: by example. Addison-Wesley Professional.

Boyer, Stuart A. 2009. SCADA: supervisory control and data acquisition. International Socie-

ty of Automation.

Choi, Donghyun, Sungjin Lee, Dongho Won ja Seungjoo Kim. 2010. “Efficient secure group

communications for SCADA”. IEEE Transactions on Power Delivery 25 (2): 714–722.

Chou, Wu, ja Li Li. 2016. Method and system for managing and using sessions as RESTful

web services. US Patent 9,509,776, marraskuu.

“Control script language”. 2018-08-15. Viitattu 6. elokuuta 2018. http://www.etm.

at/index%5C_e.asp?id=2%5C&sb1=67%5C&sb2=118.

Daneels, Axel, ja Wayne Salter. 1999. “What is SCADA?”

“Dependency Inversion Principle”. 2018-12-10. Viitattu 10. joulukuuta 2018. https://

deviq.com/dependency-inversion-principle/.

“Dependency Inversion vs Dependency Injection vs Inversion of Control vs Programming to

Interfaces”. 2018-12-10. Viitattu 10. joulukuuta 2018. https://www.equinox.co.

nz/blog/dependency-inversion-dependency-injection-inversion-

control-programming-interfaces/.

Erenkrantz, Justin Ryan. 2009. Computational REST: a new model for decentralized, internet-

scale applications. Citeseer.

Erickson, Kelvin T. 1996. “Programmable logic controllers”. IEEE potentials 15 (1): 14–17.

Erl, Thomas, Benjamin Carlyle, Cesare Pautasso ja Raj Balasubramanian. 2012. Soa with

rest: Principles, patterns &constraints for building enterprise solutions with rest. Prentice

Hall Press.

Feng, Xinyang, Jianjing Shen ja Ying Fan. 2009. “REST: An alternative to RPC for Web

services architecture”. Teoksessa Future Information Networks, 2009. ICFIN 2009. First

International Conference on, 7–10. IEEE.

76

Fernandez Adiego, B, I Prieto Barreiro ja E Blanco Vinuela. 2011. “UNICOS CPC6: automa-

ted code generation for process control applications”. Teoksessa Conf. Proc. Nide 111010,

WEPKS033. CERN-ATS-Note-2011-109 TECH.

George, Boby, ja Laurie Williams. 2004. “A structured experiment of test-driven develop-

ment”. Information and software Technology 46 (5): 337–342.

Goldenberg, Niv, ja Avishai Wool. 2013. “Accurate modeling of Modbus/TCP for intrusion

detection in SCADA systems”. International Journal of Critical Infrastructure Protection 6

(2): 63–75.

Hewitt, Carl, Peter Bishop ja Richard Steiger. 1973. “Session 8 formalisms for artificial intel-

ligence a universal modular actor formalism for artificial intelligence”. Teoksessa Advance

Papers of the Conference, 3:235. Stanford Research Institute.

Hevner, Alan, ja Samir Chatterjee. 2010. “Design science research in information systems”.

Teoksessa Design research in information systems, 9–22. Springer.

“How do you program and parameterize Modbus/TCP communication between S7-1500

CPUs and S7-1200 CPUs?” 2018-10-16. Viitattu 16. lokakuuta 2018. https://suppo

rt.industry.siemens.com/cs/document/102020340/how-do-you-

program-and-parameterize-modbus-tcp-communication-between-

s7-1500-cpus-and-s7-1200-cpus-?dti=0%5C&lc=en-WW.

Igure, Vinay M, Sean A Laughter ja Ronald D Williams. 2006. “Security issues in SCADA

networks”. Computers & Security 25 (7): 498–506.

“Interface Segregation Principle”. 2018-12-10. Viitattu 10. joulukuuta 2018. https://

deviq.com/interface-segregation-principle/.

“Ladder Logic Examples”. 2018-10-16. Viitattu 16. lokakuuta 2018. https://www.

plcacademy.com/ladder-logic-examples/.

Leppänen M., Nurminen M., Käkölä T. 2009. ITKA111 Oliosuuntautunut analyysi ja suun-

nittelu.

“Liskov Substition Principle”. 2018-12-10. Viitattu 10. joulukuuta 2018. https://devi

q.com/liskov-substitution-principle/.

77

“Managed Extensibility Framework (MEF)”. 2018-09-24. Viitattu 24. syyskuuta 2018. htt

ps://docs.microsoft.com/en-us/dotnet/framework/mef/.

Martin, Robert C. 1996. “The open-closed principle”. More C++ gems 19 (96): 9.

. 2002. Agile software development: principles, patterns, and practices. Prentice Hall.

Masse, Mark. 2011. REST API Design Rulebook: Designing Consistent RESTful Web Service

Interfaces. "O’Reilly Media, Inc.".

Maximilien, E Michael, ja Laurie Williams. 2003. “Assessing test-driven development at

IBM”. Teoksessa Software Engineering, 2003. Proceedings. 25th International Conference

on, 564–569. IEEE.

Modbus, IDA. 2004. “Modbus messaging on TCP/IP implementation guide”. v1. 0a, June 4.

“Open-Closed Principle”. 2018-12-10. Viitattu 10. joulukuuta 2018. https://deviq.

com/open-closed-principle/.

Page, David W, ja LuVerne R Peterson. 1985. Re-programmable PLA. US Patent 4,508,977,

huhtikuu.

Phan, Raphael C-W. 2012. “Authenticated modbus protocol for critical infrastructure protec-

tion”. Ieee transactions on power delivery 27 (3): 1687–1689.

Qiu, Bin, ja Hoay Beng Gooi. 2000. “Web-based SCADA display systems (WSDS) for

access via Internet”. IEEE transactions on power systems 15 (2): 681–686.

Razina, Ekaterina, ja David S Janzen. 2007. “Effects of dependency injection on maintai-

nability”. Teoksessa Proceedings of the 11th IASTED International Conference on Software

Engineering and Applications: Cambridge, MA, 7.

Rodriguez, Alex. 2008. “Restful web services: The basics”. IBM developerWorks 33.

“SIMANTIC WinCC Open Architecture - HMI Software - Siemens”. 2019-03-07. Viitattu

7. maaliskuuta 2019. https://w3.siemens.com/mcms/human- machine-

interface/en/visualization-software/simatic-wincc-open-arch

itecture/Pages/Default.aspx?vpl=References#i=1,language=en,

produkt=key_9180609/.

78

“SIMATIC WinCC Open Architecture - Basic system”. 2018-08-15. Viitattu 6. elokuuta

2018. https://w3.siemens.com/mcms/human- machine- interface/

en/visualization-software/simatic-wincc-open-architecture/

wincc-oa-basic-sw/Pages/default.aspx.

“Single Responsibility Principle”. 2018-12-10. Viitattu 10. joulukuuta 2018. https://

deviq.com/single-responsibility-principle/.

Spangenberg, Thomas, Karlheinz Cerff ja W Mexner V Kaiser. 2011. “„Tango Integration

of a SIMATIC WinCC Open Architecture SCADA System at ANKA “”. Teoksessa Procee-

dings of the 13th International Conference on Accelerator and Large Experimental Physics

Control Systems, 749–752.

“Structured Text Tutorial to Expand Your PLC Programming Skills”. 2018-09-20. Viitattu

20. syyskuuta 2018. https://www.plcacademy.com/structured- text-

tutorial//wincc-oa-basic-sw/Pages/default.aspx.

Ten, Chee-Wooi, Chen-Ching Liu ja Govindarasu Manimaran. 2008. “Vulnerability assess-

ment of cybersecurity for SCADA systems”. IEEE Transactions on Power Systems 23 (4):

1836–1846.

“The SCADA system without limits”. 2018-08-15. Viitattu 6. elokuuta 2018. https://

w3.siemens.com/mcms/human-machine-interface/en/visualization-

software/simatic-wincc-open-architecture/pages/default.aspx.

Thijssen, J. 2012. “Asynchronous operations-The RESTful cookbook”. The RESTful cook-

book.

Tiegelkamp, Michael, ja Karl-Heinz John. 1995. IEC 61131-3: Programming industrial au-

tomation systems. Springer.

“Traffic Video Analysis / Automatic Video Incident Detection - XAIDTM”. 2018-09-27. Vii-

tattu 27. syyskuuta 2018. https://www.telegra-europe.com/solutions/

solution - 54 - automatic - video - incident - detection - avid - and -

traffic-analysis-system/#61.

79

“Uusi tieliikenteen ohjausjärjestelmä (T-LOIK) nopeuttaa tiedonkulkua tienkäyttäjille ja hel-

pottaa liikennepäivystäjien työtä”. 2016-03-04. Viitattu 15. elokuuta 2018. https://www.

liikennevirasto . fi/ - /uusi - tieliikenteen - ohjausjarjestelma -

t-loik-nopeuttaa-tiedonkulkua-tienkayttajille-ja-helpottaa-

liikennepaivystajien-tyota.

Varela, Fernando, Montserrat Gonzalez Corral, Stanislaw Podgorski, Eleni Mandilara ja Uwe

Epting. 2018. “JACoW: MARS: Easing maintenance and interventions for CERN controls”.

“What is Akka.NET?” 2018-08-15. Viitattu 13. syyskuuta 2018. https://getakka.

net/articles/intro/what-is-akka.html.

80