-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtoteutus.tex
100 lines (71 loc) · 13.4 KB
/
toteutus.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
\chapter{Toteutus}
\label{ch:toteutus}
% TODO: Tarkista tekstiä, on paikoin liian yksityiskohtainen.
% TODO: UML-kuviin voisi vaihtaa arkkitehtuurissa olevia prosesseja, eikä kirjastoja.
\section{Yleiskuva}
\label{ch:rcb-sub-yleiskuva}
Kuvassa \ref{fig:rcb-sub-komponenttikaavio} on esitetty komponenttikaavio rcb\_sub-ohjelmasta ja sen käyttämistä kirjastoista. Kuvasta voi nähdä miten eri komponentit ovat relaatiossa keskenään ohjelman kanssa ja mitkä osat kommunikoivat IED-laitteen ja RabbitMQ-palvelimen kanssa.
\begin{figure}[ht!]
\includegraphics[width=1\textwidth]{pictures/rcb-sub-component-diagram.png}
\caption{Rcb\_sub-ohjelman komponenttikaavio.}
\label{fig:rcb-sub-komponenttikaavio}
\end{figure}
Toteutukseen valittiin seuraavat kirjastot:
\begin{itemize}
\item \emph{libIEC61850} \cite{libIEC61850-repo},
\item \emph{rabbitmq-c} \cite{rabbitmq-c-repo},
\item \emph{jansson} \cite{jansson-repo}, ja
\item \emph{Argp} \cite{argp-glibc-guide}.
\end{itemize}
Kaikki käytetyt kirjastot ovat toteutettu C-kielelle. Kirjastojen tarkoitus on abstrahoida tietyn asian käyttö, ja tarjota käyttäjälle siitä helppokäyttöinen ja ymmärrettävä rajapinta. LibIEC61850-kirjasto abstrahoi IEC 61850 -standardin käyttöä ja hoitaa matalan tason MMS-protokollan kommunikoinnin \cite{libIEC61850-repo}. Samaa kirjastoa käytettiin myös demoversiossa ja kirjaston kerrosarkkitehtuuri esitettiin aikaisemmin kuvassa \ref{fig:libiec61850-layer-architecture}. Kuvassa \ref{fig:rcb-sub-komponenttikaavio} libIEC61850 kommunikoi suoraan IED-laitteen kanssa MMS-protokollaa käyttäen. Rabbitmq-c-kirjasto abstrahoi RabbitMQ-palvelimen käytön ja hoitaa matalan tason AMQP-pohjaisen kommunikoinnin \cite{rabbitmq-c-repo}. Toteutuksessa rabbitmq-c kommunikoi suoraan RabbitMQ-palvelimen kanssa. Jansson-kirjasto abstrahoi JSON-rakenteiden lukua ja käsittelyä C-kielelle \cite{jansson-repo}. Kirjastoa käytettiin muuntamaan IEC 61850 -standardin viesti JSON-muotoon. JSON-rakenne on nähtävissä liitteessä \ref{ch:report-json-format}. Argp-kirjasto auttaa ohjelman komentoriviparametrien määrittämisessä ja käsittelyssä \cite{argp-glibc-guide}. Argp-kirjastolla voidaan toteuttaa \emph{UNIX}-tyyliset \emph{parametrit} (\emph{arguments}) ja \emph{valitsimet/vivut} (\emph{options/switches}) \cite{step-by-step-into-argp}.
Kuvassa \ref{fig:rcb-sub-sekvenssikaavio} on esitetty rcb\_sub-ohjelman sekvenssikaavio pääpiirteisestä toiminnasta. Ohjelman noudattaa osin demon toimintaperiaatetta (kuvat \ref{fig:sequence-diagram-report-subscription} ja \ref{fig:sequence-diagram-report-subscription-processing}). Seuraavaksi käydään läpi ohjelman pääpiirteinen toiminta ja myöhemmin jokainen kohta tarkemmin läpi kappaleessa \ref{rcb-sub-toiminta}. Ohjelman suoritus alkaa lukemalla annetut parametrit ja vivut Argp-kirjastolla (kohdat 1--2). Parametreissa tulee tiedot yhteyden muodostamiseen IED-lait\-teel\-le ja RabbitMQ-palvelimelle (kohdat 3--6). Parametreissa on myös tiedot RCB-ins\-tans\-seis\-ta, jotka halutaan IED:ltä tilata. Yhteyksien muodostamisen jälkeen jokainen parametrina annettu RCB käydään läpi silmukassa ja sen arvot ja datajoukon viitteet luetaan IED:ltä (kohdat 7--12). Tämän jälkeen sisäkkäisessä silmukassa luetaan datajoukon viitteiden muuttujien \emph{spesifikaatiot} (kohdat 11--12). Spesifikaatio antaa tiedot muuttujien pituudesta ja tyypistä, jotka lisätään JSON:iin myöhemmin. Tämän jälkeen tehdään toinen silmukka, jossa jokainen RCB-instanssi tilataan ja niille asetetaan takaisinkutsufunktio (kohdat 13--16). Arvojen kirjoitushetkellä (kohta 15) RCB varataan ja se aloittaa viestien lähettämisen. Jokaisen RCB:n kirjoituksen jälkeen ohjelma jää loputtomaan silmukkaan ottamaan viestejä vastaan (kohdat 17--22). Viestin saapuessa kutsutaan asetettua takaisinkutsufunktiota, jonka parametrina on saapunut viesti (kohta 17). Viesti muutetaan JSON-muotoon jansson-kirjastolla ja julkaistaan RabbitMQ-palvelimelle rabbitmq-c-kirjastolla (kohdat 18--21).
\begin{figure}[ht!]
\includegraphics[width=1\textwidth]{pictures/rcb-sub-general-sd.png}
\caption{Sekvenssikaavio rcb\_sub-ohjelman kokonaistoiminnasta.}
\label{fig:rcb-sub-sekvenssikaavio}
\end{figure}
\section{Ohjelman toiminta}
\label{rcb-sub-toiminta}
Tulevissa kappaleissa käydään läpi tarkemmin rcb\_sub-ohjelman toimintaa. Kappaleiden järjestys noudattaa kuvassa \ref{fig:rcb-sub-sekvenssikaavio} olevan sekvenssikaavion järjestystä ja jokainen kappale tarkentaa tiettyä osaa siitä. Toisin sanoen ohjelmaa käydään tarkemmin läpi sen suorituksen järjestyksessä.
\subsection{Parametrisointi}
Ohjelma parametrisoitiin Argp-kirjastolla. Kirjasto tarjoaa rajapinnan komentoriviparametrien käsittelyyn ja määrittämiseen. Parametrien muodot ovat tutut muista Linux-käyt\-tö\-jär\-jes\-tel\-män parametreista ja samaa periaatetta käytettiin tässäkin ohjelmassa. Kirjasto myös lisäsi ohjelmaan automaattisesti aputekstin käyttäjää varten. Aputeksti sisältää tietoa ohjelman parametreista ja niiden käytöstä. Aputekstin pystyi tulostamaan vivulla \texttt{-{}-help}. Liitteessä \ref{ch:rcb-sub-help-output} on esitetty ohjelman tulostama aputeksti. Liitteestä voi myös nähdä kaikki ohjelman parametrit ja lyhyen selityksen mihin kutakin käytetään. Aputeksti ei sinänsä ollut tarpeellinen, koska muu järjestelmä hallitsee ohjelman suoritusta ja parametrien antamista. Se kuitenkin päätettiin lisätä pienen vaivan vuoksi ja toimii hyvänä dokumentaationa myöhemmin.
Ohjelmiston parametrien ja vipujen voidaan ajatella koostuvan kolmesta eri ryhmästä (liite \ref{ch:rcb-sub-help-output} rivit 1--4). Ensin päätason vaihtoehtoiset vivut \texttt{OPTIONS} (rivi 1). Pakolliset parametrit \texttt{EXCHANGE} ja \texttt{ROUTING\_KEY} (rivi 2). Viimeisenä ryhmänä \texttt{RCB\_REF} parametri ja siihen liittyvät vivut \texttt{RCB\_OPTIONS} (rivi 3). Näitä ryhmiä voi olla n-kappaletta, mutta vähintään yksi. Liitteessä \ref{ch:rcb-sub-help-output} riveillä 71--72 on esitetty esimerkki, joka tilaa viestit IED-laitteelta osoitteesta 192.168.2.220. AMQP-vaihteen nimi on \emph{testexchange} ja reititysavaimen nimi on \emph{testkey}. IED-laitteelta tilataan RCB-instanssi viitteellä MY\_LD0""/""LLN0"".""BR"".""rcbMeas01. Instanssille asetetaan yleinen kysely (\texttt{-g1}), liipaisimet (\texttt{-t27}) ja viestin vaihtoehtoiset kentät (\texttt{-o16}). Liipaisimet ja vaihtoehtoiset kentät annetaan numeroarvoilla summaamalla niitä yhteen. Vaihtoehdot näkee ohjelman aputekstistä (esimerkiksi liipaisimet riveillä 53--58).
Suurin osa \texttt{OPTION} vivuista ovat itsestäänselviä. Esimerkkinä \texttt{-{}-amqp-host}, joka kertoo AMQP-pal\-ve\-li\-men IP-osoitteen, ja \texttt{-{}-ied-host}, joka kertoo IED-laitteen IP-osoitteen. Parametrit \texttt{EXCHANGE} ja \texttt{ROUTING\_KEY} määrittävät nimet RabbitMQ-pal\-ve\-li\-men vaihteelle ja reititysavaimelle. Parametri \texttt{RCB\_REF} määrittää viitteen tilattavaan RCB-instanssiin IED-laitteella. Tätä seuraa vaihtoehtoinen \texttt{RCB\_OPTIONS} vipu, joka määrittää edeltävän instanssin kirjoitettavat arvot ennen tilausta. Sillä voidaan määrittää mm. käytetyt vaihtoehtoiset kentät (\texttt{-{}-opt-fields}), käytetyt liipaisimet (\texttt{-{}-trigger}).
\subsection{Yhteyksien muodostus}
Parametrien luvun jälkeen ohjelma muodostaa yhteydet ensin RabbitMQ-palvelimelle ja sen jälkeen IED-laitteelle. Kuvassa \ref{fig:rcb-sub-open-connections} on esitetty sekvenssikaavio, joka näyttää mitä kirjaston funktioita ohjelma kutsuu missäkin järjestyksessä. Funktiot ja niiden parametrit voi tarkemmin tarkistaa kirjastojen omista dokumentaatioista \cite{libIEC61850-doc} \cite{rabbitmq-c-repo}. Tämä tarkentaa yleiskuvasta \ref{fig:rcb-sub-sekvenssikaavio} kohdat 3--6. Kaaviossa ohjelma muodostaa yhteydet vain kerran. Ohjelma on kuitenkin toteutettu niin, että se yrittää muodostaa yhteydet uudestaan vikatilanteissa. Jos muodostus ei onnistu, ohjelma kirjoittaa lokin tapahtuneesta ja odottaa hetken ennen uudelleen yritystä.
\begin{figure}[ht!]
\includegraphics[width=1\textwidth]{pictures/rcb-sub-open-connections.png}
\caption{Sekvenssikaavio kuinka rcb\_sub avaa yhteydet RabbitMQ-palvelimelle ja IED-laitteelle.}
\label{fig:rcb-sub-open-connections}
\end{figure}
Yhteyden avauksen ja sisäänkirjautumisen jälkeen ohjelma avaa kanavan kohdassa 7--8. Kanava on yhteyden päälle avattu oma erillinen kommunikointiväylä, joka ei sotkeudu muihin kanaviin. Yhteen avattuun yhteyteen voi olla avattuna monta eri kanavaa. Kanavat mahdollistavat sen, että sama yhteys voidaan jakaa monen säikeen kanssa.
\subsection{IED:n muuttujien tietojen luku}
Yhteyksien muodostamisen jälkeen ohjelma käy läpi silmukassa jokaisen parametrina annetun RCB:n viitteen. Lukee RCB:n datajoukon viitteet ja selvittää sen jokaisen muuttujan spesifikaatiot. Kuvassa \ref{fig:rcb-sub-reading-specifications} on esitetty sekvenssikaavio toiminnasta. Kuva tarkentaa yleiskuvassa \ref{fig:rcb-sub-sekvenssikaavio} kohtia 7--12.
\begin{figure}[ht!]
\includegraphics[width=1\textwidth]{pictures/rcb-sub-reading-specifications.png}
\caption{Sekvenssikaavio kuinka rcb\_sub lukee RCB-instanssin arvot ja muuttujien spesifikaatiot.}
\label{fig:rcb-sub-reading-specifications}
\end{figure}
Ensin RCB:sta luetaan sen tiedot IED-laitteelta. RCB:ltä saadaan tieto mihin datajoukkoon se on liitetty. Tämän jälkeen selvitetään kaikki datajoukossa olevien muuttujien spesifikaatiot. Luetut tiedot tallennetaan ja niitä käytetään täydentämään muuttujien tietoja JSON-viestiin. Jokaiseen muuttujaan lisätään sen viite, tyyppi ja koko bitteinä. Esimerkkinä tästä on liitteessä \ref{ch:report-json-format} riveillä 21--22.
\subsection{Viestien tilaus}
Ohjelman luettua kaikki muuttujien spesifikaatiot. Ohjelma tilaa silmukassa parametrina annetut RCB-instanssit. Kuvassa \ref{fig:rcb-sub-subscribe-reports} on esitetty sekvenssikaavio toiminnasta. Kuva tarkentaa yleiskuvassa \ref{fig:rcb-sub-sekvenssikaavio} kohtia 13--16.
\begin{figure}[ht!]
\includegraphics[width=1\textwidth]{pictures/rcb-sub-subscribe-reports.png}
\caption{Sekvenssikaavio kuinka rcb\_sub tilaa RCB-instanssit.}
\label{fig:rcb-sub-subscribe-reports}
\end{figure}
Jokainen IED-laitteen RCB-instanssi konfiguroidaan ja varataan ennen tilausta. Ohjelma kirjoittaa parametrina annetut liipaisimet ja vaihtoehtoiset kentät instanssiin. Jokaiselle instanssille täytyy myös asettaa takaisinkutsufunktio, jota kirjasto tulee kutsumaan viestin saapuessa. RCB-instanssi aloittaa tilauksen heti kun se varataan. Seurauksena on, että ohjelma tulee käsittelemään viestejä samalla, kun muita RCB-instansseja tilataan.
\subsection{JSON:in muodostaminen ja julkaisu}
Viestin saapuessa libIEC61580-kirjasto kutsuu asetettua takaisinkutsufunktiota. Takaisinkutsufunktio muuttaa viestin JSON-muotoon ja lisäsi siihen aikaisemmin luetut muuttujien viitteet, tyypit ja koot. Tämän jälkeen JSON-julkaistiin RabbitMQ-palvelimelle. Kuvissa \ref{fig:rcb-sub-report-to-json-1} ja \ref{fig:rcb-sub-report-to-json-2} on esitetty sekvenssikaaviolla, kuinka ohjelma muuttaa viestin JSON:iksi ja julkaisee RabbitMQ:lle. Kuva \ref{fig:rcb-sub-report-to-json-1} jatkuu kuvassa \ref{fig:rcb-sub-report-to-json-2}. Kuva \ref{fig:rcb-sub-report-to-json-1} tarkentaa yleiskuvan \ref{fig:rcb-sub-sekvenssikaavio} kohtia 17--19 ja kuva \ref{fig:rcb-sub-report-to-json-2} kohtia 20--22. Aikaisemmin mainittiin, että libIEC61850-kirjasto toteuttaa sisäisen puskurin viestien vastaanottoon ja käsittelee siitä yhden viestin kerrallaan. Kirjasto varaa yhden puskurin avattua yhteyttä kohti. Puskurista käsitellään seuraava viesti, kun edellinen takaisinkutsufunktion suoritus on palannut. Rcb\_sub avaa vain yhden yhteyden IED-laitteeseen. Seurauksena on, että viestejä ei prosessoida rinnakkain missään vaiheessa suoritusta.
\begin{figure}[ht!]
\includegraphics[width=1\textwidth]{pictures/rcb-sub-report-to-json.png}
\caption{Sekvenssikaavio kuinka rcb\_sub muodostaa JSON:in päätason kentät.}
\label{fig:rcb-sub-report-to-json-1}
\end{figure}
Kuvassa \ref{fig:rcb-sub-report-to-json-1} suoritus alkaa, kun libIEC61850-kirjasto kutsuu takaisinkutsufunktiota viestin saapuessa. Funktiolle annetaan parametrina saapunut viesti \emph{ClientReport}-struktuurin instanssina. Tämän jälkeen ohjelma käy läpi viestin jokaisen päätason kentän ja lisää ne JSON-rakenteeseen. Osa viestin kentistä on vaihtoehtoisia riippuen siitä, mitä käyttäjä asetti \texttt{-{}-opt-fields} vivun parametrilla. Jos arvoa viestissä ei ole, korvataan se null-arvolla JSON:iin. Tämän jälkeen suoritus jatkuu kuvasta \ref{fig:rcb-sub-report-to-json-1} kuvaan \ref{fig:rcb-sub-report-to-json-2}.
\begin{figure}[ht!]
\includegraphics[width=1\textwidth]{pictures/rcb-sub-report-to-json_001.png}
\caption{Sekvenssikaavio kuinka rcb\_sub lisää JSON:iin muuttujat viestistä.}
\label{fig:rcb-sub-report-to-json-2}
\end{figure}
Päätason viestin kenttien jälkeen ohjelma käy läpi silmukassa viestiin sisällytetyt muuttujien arvot. Tässä vaiheessa ohjelma yhdistää aikaisemmin luetut muuttujien spesifikaatiot viestin muuttujiin. IEC 61850 -standardin mukainen viesti sisältää vain taulukon muuttujien arvoja. Jotta muuttujan arvon ja aikaisemmin luetun spesifikaation yhdistäminen on mahdollista. Ohjelma pakottaa vaihtoehtoisen syykoodi-kentän päälle viestiin. Tämän avulla saadaan selville tarvittava muuttujan indeksi, joka mahdollistaa tiedon yhdistämisen. Kokonaan muutettu viesti julkaistaan RabbitMQ:lle ja takaisinkutsufunktio palaa.