i
Auteursrechtelijke bescherming De auteur geeft de toelating deze scriptie voor raadpleging beschikbaar te stellen en delen ervan te kopiëren voor persoonlijk gebruik. Elk ander gebruik valt onder de beperkingen van het auteursrecht, in het bijzonder met betrekking tot de verplichte bronvermelding bij het gebruiken of aanhalen van teksten of resultaten uit deze scriptie.
ii
Woord vooraf Het zoeken naar een thesisonderwerp is niet altijd makkelijk. Daarom wil ik de mensen bij Infrabel bedanken dat zij mij deze kans hebben aangeboden. Ik wil ten eerste Juliette Delbecque bedanken voor alle papieren in orde te brengen zodat ik bij Infrabel mijn stage kon beginnen. Mijn grootste dankbetuiging gaat uit naar Bart Van der Spiegel, mijn promotor bij Infrabel, en Mattias Jans die mij bij Infrabel goed hebben opgevangen, opgevolgd en steeds met een antwoord op mijn vragen klaar stonden. Ik wil ook mijn docenten van mijn bacheloropleiding elektromechanica en mijn masteropleiding elektrotechniek (automatisering) bedanken voor het bijdragen van de kennis waarover ik momenteel beschik. Vooral mijn promoter, Paul Vander Haeghen, wil ik hierbij bedanken voor de steun en de opvolging bij mijn thesis. Tevens wil ik Luc Dhondt en Patrick Vangheluwe bedanken voor de rondleiding in respectievelijk het station van Brugge en Gent Sint-Pieters. Ook de bijkomende uitleg hierbij over onder andere assentellers, spoorstroomkringen, PLP’s en EBP’s hebben een grote bijdrage aan mijn thesis geleverd. De mensen van de Energie Beheer Cel wil ik ook bedanken voor de vriendelijke en aangename werksfeer waarin ze mij aan mijn thesis hebben laten werken. Mijn laatste dankbetuiging gaat uit naar mijn ouders, mijn zussen en mijn vriendin want zij hebben steeds in mij geloofd. Daarbij wil ik mijn ouders nog eens extra bedanken want het is dankzij hun morele en financiële steun dat ik mijn studieloopbaan heb kunnen doorlopen.
Jil Van Wetter Gent, mei 2014
iii
Abstract Sinds enkele jaren worden treinen van energiemeters voorzien. Deze meters meten het exacte energieverbruik of eventuele energieteruggave bij een treinrit. Bij de locomotieven die (nog) niet over een meter beschikken, wordt een schatting van het energieverbruik gedaan. Het programma Erex van het bedrijf Eress test de gegevens van deze meters met behulp van validatieregels. Indien de metergegevens hier niet aan voldoen, wordt eveneens een schatting gebruikt. Is wel voldaan aan de validatieregels dan kunnen de gemeten waarden gebruikt worden. Infrabel stelt op basis van deze schattingen en/of metergegevens via Erex maandelijks een factuur op voor haar verschillende klanten. In de toekomst zullen steeds meer treinen van een energiemeter voorzien zijn. Het is hierbij niet wenselijk dat metergegevens verworpen worden en schattingen gebruikt worden omdat de metergegevens het exacte en niet een geschat verbruik geven. Hoe meer metergegevens gebruikt kunnen worden, hoe nauwkeuriger de uiteindelijke factuur. Deze thesis houdt zich bezig met twee van deze validatieregels. Hierbij zijn eveneens programma’s geschreven (in Java) die ervoor zorgen dat de metergegevens toch gebruikt kunnen worden. Hierbij wordt er gezocht naar de juiste combinatie van een energiemeter met één of meerdere treinritten. Het gaat hier om de verwerking van veel gegevens en daarom wordt met databanken gewerkt (sql). De uiteindelijke uitvoer van het programma zijn dus voorstellen van meters gekoppeld aan treinritten. Deze voorstellen kunnen dan door Erex opnieuw gecontroleerd worden op basis van de resterende validatieregels.
Several trains in Belgium have been provided with energy meters. These meters measure the exact energy consumption during a train ride. An estimation of the consumed energy is used for those trains that do not possess a meter. The program Erex tests the data received from the meters using validation rules. When one of these rules isn’t validated, then Erex will also use an estimation instead of the measured energy. Every month Infrabel uses these estimations and/or metered data to draft an invoice for each customer and Erex is the program that makes this possible. In the future more and more trains will be provided with an energy meter. When the data of a meter is rejected and the estimation is used, then the invoice will be less accurate. This thesis concentrates on two validation rules. Several programs have been written in Java and they make it possible that the once rejected metered data can still be used. The programs search for the right combination between an energy meter and one or more train rides. Because the programs have to process a lot of data, databases will be used (sql). The output of the program consists of propositions. These propositions show the combination of an energy meter with one or more train rides. Erex will have to validate these propositions based on the other validation rules.
iv
Inhoudsopgave Auteursrechtelijke bescherming.......................................................................................................... ii Woord vooraf .................................................................................................................................... iii Abstract ............................................................................................................................................. iv Inhoudsopgave ...................................................................................................................................1 Inleiding..............................................................................................................................................6 Hoofdstuk 1: Situering ........................................................................................................................7 1.1
NMBS-groep ........................................................................................................................7
1.2
Elektrische tractie ................................................................................................................8
1.3
Keet.....................................................................................................................................9
1.4
Bepaling van het treinverbruik........................................................................................... 11
1.4.1
Methodes .................................................................................................................. 11
1.4.2
Schatting .................................................................................................................... 11
1.4.3
Meters ....................................................................................................................... 11
1.4.4
Eress en Erex.............................................................................................................. 12
Hoofdstuk 2: Huidige situatie en probleemstelling ............................................................................ 14 2.1
Huidige situatie ................................................................................................................. 14
2.1.1
Dataflow naar Erex .................................................................................................... 14
2.1.2
Verwerking van deze gegevens aan de hand van validatieregels................................. 15
2.2
Probleemstelling................................................................................................................ 15
Hoofdstuk 3: Algoritme ..................................................................................................................... 17 3.1
Oorzaken ........................................................................................................................... 17
3.2
Algoritmes ......................................................................................................................... 18
3.2.1
Samenvatting ............................................................................................................. 18
3.2.2
Algemeen overzicht ................................................................................................... 19
3.2.3
Algoritme van het hoofdprogramma voor de eerste validatieregel ............................. 21
3.2.4
Algoritme van het hoofdprogramma voor de tweede validatieregel ........................... 24
Hoofdstuk 4: Input ............................................................................................................................ 26 4.1
Assentellers ....................................................................................................................... 26
4.2
Spoorstroomkringen .......................................................................................................... 30
4.2.1
Gewone spoorstroomkringen..................................................................................... 30
4.2.1.1
Circuit van de stroom ............................................................................................. 30
4.2.1.2
Werkingsprincipe ................................................................................................... 33
1
4.2.1.3 4.2.2
Geheel van gesloten stroomcircuit en spoorstroomkring........................................ 34 Jade of toonfrequente spoorstroomkringen ............................................................... 35
4.2.2.1
Algemeen............................................................................................................... 35
4.2.2.2
Serieresonantie ...................................................................................................... 36
4.2.2.3
Parallelresonantie .................................................................................................. 37
4.2.2.4
Vormen van een blokkeerfilter op basis van de resonantiefrequentie .................... 43
4.3
Vergelijking van een spoorstroomkring en een assenteller................................................. 51
4.4
Energiemeters ................................................................................................................... 52
4.4.1
Ingangen van de energiemeter................................................................................... 53
4.4.1.1
Algemeen............................................................................................................... 53
4.4.1.2
Spanningsomvormer .............................................................................................. 53
4.4.1.3
Stroomomvormer .................................................................................................. 54
4.4.2
Meetprincipe van de energiemeter ............................................................................ 57
4.4.3
Conversies ................................................................................................................. 58
4.4.3.1
Digitaal analoog conversie (DAC) ............................................................................ 58
4.4.3.2
Analoog digitaal conversie (ADC) ............................................................................ 58
4.4.3.3
sigma-delta analoog digitaal conversie ................................................................... 62
4.4.4 4.4.41
Wisselspanningvermogens ..................................................................................... 64
4.4.41
Gelijkspanningvermogens ...................................................................................... 66
4.4.5 4.5
Processor ................................................................................................................... 64
Global positioning system .......................................................................................... 67
Globaal beeld: energie- en informatieflow ......................................................................... 68
Hoofdstuk 5: Excel, databanken en Java ............................................................................................ 78 5.1
Excel .................................................................................................................................. 78
5.2
Databanken ....................................................................................................................... 78
5.2.1
SQL ............................................................................................................................ 81
5.2.2
Voorbeelden .............................................................................................................. 82
5.3
Java ................................................................................................................................... 92
5.3.1
Datatypes .................................................................................................................. 92
5.3.2
Controlestructuren .................................................................................................... 92
5.3.2.1
de if-opdracht ........................................................................................................ 93
5.3.2.2
De for-lus ............................................................................................................... 94
5.3.2.3
de while-lus en de do-while-lus .............................................................................. 95
5.3.3
Methodes .................................................................................................................. 97 2
5.3.4
Rijen en lijsten ........................................................................................................... 99
5.3.5
External jars ............................................................................................................... 99
5.3.5.1
Joda Time............................................................................................................... 99
5.3.5.2
MySQL Connector .................................................................................................. 99
5.3.5.3
POI ....................................................................................................................... 100
5.3.5.4
Toevoegen van jars .............................................................................................. 100
5.3.6
Thesis ...................................................................................................................... 101
Hoofdstuk 6: Software .................................................................................................................... 102 6.1
Programma om metergegevens naar de databank te sturen ............................................ 102
6.1.1
Bibliotheken ............................................................................................................ 102
6.1.2
Voorbereiding .......................................................................................................... 103
6.1.3
Selecteren van Excel-bestand ................................................................................... 104
6.1.4
Connectie met MySQL en aanmaken van databank .................................................. 105
6.1.5
Aanmaken van tabellen binnen de databank ............................................................ 105
6.1.6
Invullen van kolommen binnen de databanktabel .................................................... 106
6.1.7
Ledigen van ArrayLists en afsluiten .......................................................................... 109
6.1.8
Lopen van het programma voor de energiemetergegevens ...................................... 110
6.2
Programma om TMS-data naar de databank te schrijven ................................................. 112
6.2.1
Bibliotheken en voorbereiding ................................................................................. 112
6.2.2
Selecteren van Excel-bestand ................................................................................... 113
6.2.3
Connectie met MySQL en aanmaken en invullen van de tabel .................................. 114
6.2.4
Ledigen van ArrayLists en afsluiten .......................................................................... 125
6.2.5
Probleem van “heap space” ..................................................................................... 127
6.2.6
Lopen van het programma voor de TMS-data .......................................................... 129
6.3
Hoofdprogramma: deel 1................................................................................................. 131
6.3.1
Importeren van de bibliotheken ............................................................................... 131
6.3.2
Meegeven van gegevens .......................................................................................... 131
6.3.3
Connectie met de databank en toevoegen van kolom .............................................. 132
6.3.4
Afsluiten van het programma................................................................................... 133
6.3.5
Lopen van het hoofdprogramma: deel 1 .................................................................. 133
6.4
Hoofdprogramma: deel 2................................................................................................. 135
6.4.1
Importeren van de bibliotheken en aanmaken van ArrayLists .................................. 136
6.4.2
Declareren, ingeven en verbinden............................................................................ 137
6.4.3
Informatie naar de gebruiker toe ............................................................................. 138 3
6.4.4
Gegevens van de energiemeter in ArrayLists zetten ................................................. 139
6.4.5
Detectiepuntgegevens in ArrayLists zetten ............................................................... 139
6.4.6
Vergelijken van de energiemeter met de TMS-data .................................................. 140
6.4.7
Afsluiten van het programma................................................................................... 141
6.4.8
Methode last ........................................................................................................... 143
6.4.9
Methode fill ............................................................................................................. 143
6.4.10
Methode fill2 ........................................................................................................... 144
6.4.11
Methode between ................................................................................................... 145
6.4.12
Methode bOK .......................................................................................................... 146
6.4.13
Lopen van het hoofdprogramma: deel 2 .................................................................. 147
6.5
Hoofdprogramma: deel 3................................................................................................. 150
6.5.1
Importeren van de bibliotheken en aanmaken van ArrayLists .................................. 152
6.5.2
Declareren, ingeven en verbinden............................................................................ 152
6.5.3
Aanmaken van de kolom ‘propose’ in de tabel van de meter ................................... 153
6.5.4
Invullen van een ArrayList met de waarden uit de ‘bothOK’-kolom .......................... 154
6.5.5
Invullen van de resterende ArrayLists....................................................................... 154
6.5.6
De kolom ‘propose’ invullen in de tabel van de databank ......................................... 156
6.5.7
Afsluiten van het programma................................................................................... 157
6.5.8
Methode last ........................................................................................................... 158
6.5.9
Methode fill_bothOK ............................................................................................... 159
6.5.10
Methode find ........................................................................................................... 159
6.5.11
Methode order ........................................................................................................ 161
6.5.12
Methode propose_position...................................................................................... 162
6.5.13
Methode propose_fill .............................................................................................. 163
6.5.14
Lopen van het programma ....................................................................................... 164
Hoofdstuk 7: Bespreking van de resultaten ..................................................................................... 169 7.1
Gevonden combinaties .................................................................................................... 169
7.2
Tijd .................................................................................................................................. 171
7.3
Eventuele aanvullingen.................................................................................................... 172
Algemeen besluit ............................................................................................................................ 173 Lijst met figuren en tabellen ........................................................................................................... 174 Figuren ....................................................................................................................................... 174 Tabellen ...................................................................................................................................... 177 Bronnen.......................................................................................................................................... 178 4
Geraadpleegde literatuur................................................................................................................ 180 Bijlage 1: cd .................................................................................................................................... 181 Bijlage 2: Engelse bespreking .......................................................................................................... 182
5
Inleiding De opdracht van deze thesis kwam van de Energie Beheer Cel van het bedrijf Infrabel. Infrabel is de infrastructuurverantwoordelijke bij de Belgische spoorwegen. De Energie Beheer Cel, gelegen in Brussel, houdt zich onder andere bezig met het opstellen van de energiefacturen voor zijn verschillende klanten. Deze klanten rijden namelijk met treinen over het Belgische spoorwegnet en verbruiken hierbij elektrische energie (tractie-energie). Sinds enkele jaren rijden er een aantal locomotieven met een energiemeter. Deze meters berekenen het exacte energieverbruik (en eventuele teruggave) van een treinrit. Om tot een juiste energiesettlement (en later facturatie) te komen, maakt Infrabel gebruik van het Noorse programma ‘Erex’. Erex bepaalt aan de hand van validatieregels of de data van deze energiemeters al dan niet gebruikt kunnen worden. Wanneer de metergegevens niet gebruikt kunnen worden, wordt een schatting van de energie doorgevoerd. Deze schatting is minder nauwkeurig dan het gebruik van een energiemeter. De klanten van Infrabel krijgen dus op hun factuur een combinatie van energiemetergegevens en schattingen, waarvan de eerste het nauwkeurigst zijn. Aangezien in de toekomst steeds meer treinen van een energiemeter voorzien zullen worden, is het nefast voor de juiste facturatie van het treinverbruik als de gegevens van de energiemeters niet gebruikt kunnen worden. Er moet dan namelijk overgeschakeld worden naar schattingen die niet het exacte verbruik geven. Het komt er dus op neer dat hoe meer data van de meters gebruikt kunnen worden, hoe nauwkeuriger de factuur voor elke klant is. Het doel van deze thesis is het schrijven van een programma dat ervoor zorgt dat de gegevens van de afgewezen energiemeters toch nog gebruikt kunnen worden. Hiervoor wordt er gekeken naar twee validatieregels van Erex. De thesis bestaat in totaal uit zeven hoofdstukken. De eerste twee hoofdstukken zijn de inleidende hoofdstukken. Het eerste hoofdstuk beslaat de situering van deze thesis en legt enkel zaken en begrippen uit die belangrijk zijn voor deze thesis. Het tweede hoofdstuk gaat nog wat dieper in over de huidige situatie en de probleemstelling die hierboven werd beschreven. Het derde hoofdstuk bevat de algoritmes die vertellen hoe het probleem aangepakt zal worden. Het vierde hoofdstuk beslaat de inputs die belangrijk zijn voor het tot stand komen van de facturatie van de tractie-energie (o.a. energiemeters). Het vijfde hoofdstuk bevat de uitleg over de softwaretalen die in deze thesis gebruikt werden, namelijk Java en sql om ten slotte over te gaan naar het zesde hoofdstuk dat alle programma’s en bijhorende uitleg bevat. Het zevende hoofdstuk bespreekt tenslotte de bekomen resultaten.
6
Hoofdstuk 1: Situering 1.1
NMBS-groep
De NMBS-groep bestond uit drie bedrijven: NMBS-holding, NMBS en Infrabel. Samen stonden ze in voor het treinvervoer in België en alles wat daarbij hoort. NMBS-holding vormde de overkoepelende holding van de NMBS-groep. Ze stond in voor het beheer van al het personeel en sociale betrekkingen. Ze zorgde eveneens voor de onroerende goederen van de NMBS waaronder ook de stations. NMBS zorgt voor de exploitatie van de treinen. Hierbij hoort zowel het vervoer van goederen als passagiers. Infrabel is de infrastructuurbeheerder van de Belgische spoorwegen en is zo verantwoordelijk voor de veiligheid, het onderhoud en de ontwikkeling van het spoornet (sporen, bovenleiding, bruggen, …). Ze regelt eveneens het treinverkeer (centrale dienst en seinhuizen) en zorgt er alsook voor dat allerlei spoorwegondernemingen van het spoornet gebruik kunnen maken. Alle drie bedrijven vormden een zelfstandig overheidsbedrijf. De structuur hiervan wordt hieronder afgebeeld.
Figuur 1: De structuur van de NMBS-groep (NMBS-holding, z.j.)
Op 30 augustus 2013 werd er een wet ingevoerd waardoor deze structuur hervormd moest worden. Bijgevolg bestaat vanaf 1 januari 2014 de NMBS-holding niet meer. De holding werd onder de NMBS gebracht en haar functies werden verdeeld over de NMBS en Infrabel. HR-Rail N.V. werd eveneens opgericht en is een dochteronderneming van de NMBS en Infrabel. HR-Rail N.V. is de werkgever van het personeel, zowel die van Infrabel als die van de NMBS.
7
1.2
Elektrische tractie
Met elektrische tractie wordt de energie bedoeld die gebruikt wordt voor het aandrijven van elektrische locomotieven en/of motorstellen. Deze energie wordt eveneens genuttigd voor andere zaken bij reizigerstreinen zoals verwarming, airco en verlichting. Infrabel zorgt ervoor dat de spoorwegondernemingen deze tractie-energie kunnen afnemen. Elia, de netbeheerder van het Belgische hoogspanningsnet, beheert de elektriciteitsnetten van 30 kV tot en met 380 kV. Elia garandeert dat er steeds een evenwicht is tussen vraag en aanbod van elektrische energie op dit net. De tractieonderstations van Infrabel zijn voor het grootste deel verbonden met het net van Elia. Deze elektrische energie wordt geproduceerd in elektriciteitscentrales (op basis van kolen, gas, olie, nucleaire energie, wind, …), waarna ze getransporteerd wordt op het hoogspanningsnet. Zoals eerder vermeld zijn de tractieonderstations van Infrabel met het Elia-net verbonden. Hier wordt de spanning omgevormd (met behulp van transformatoren en eventuele gelijkrichters) en via de bovenleiding verdeeld. De spanningen waarop treinen in België rijden zijn 3 kV DC en 25 kV AC (hogesnelheidstreinen). Een trein kan dan met een stroomafnemer de nodige elektrische energie afnemen van de bovenleiding. Een voorbeeld van een veelgebruikte stroomafnemer is een pantograaf. Een afbeelding van een pantograaf wordt hieronder weergegeven.
Figuur 2: Pantograaf (Stroomafnemer, z.j.)
Deze tractie-energie loopt dus een weg af, vertrekkende van de centrale waarin hij opgewekt werd, lopende over het elektriciteitsnet met een hoge wisselspanning naar het tractieonderstation van Infrabel waar de spanning omgevormd wordt om ten slotte geleid te worden over de bovenleiding waar met behulp van stroomafnemers de energie genuttigd kan 8
worden door bijvoorbeeld een locomotief. In onderstaande afbeelding wordt deze weg nog eens gedemonstreerd.
Figuur 3: Overzicht van de afgelegde weg van de tractie-energie (Cel energiebeheer, 2012)
Infrabel zal dus voor elke spoorwegonderneming die gebruik maakt van deze tractie-energie maandelijks een factuur moeten opstellen. Hoe men tot deze factuur komt, wordt in een volgend deel uitgelegd.
1.3
Keet
Het tractieonderstation zorgt niet enkel voor de energielevering van de bovenleiding. Het zorgt er eveneens voor dat de talrijke keten langs de sporen gevoed kunnen worden. In onderstaande afbeelding worden drie keten langs de spoorweg weergegeven.
9
Figuur 4: Drie keten langs de spoorwegen in de nabijheid van het station van Brugge
Een keet op zich is een leegstaande behuizing langs de kant van een spoorweg. Deze keten kunnen verschillende functies hebben naargelang hun inhoud en worden steeds gevoed op 1 kV AC. Zo zorgen ze onder andere voor de voeding van de detectiepunten (assentellers, SK’s, …) en de voeding van allerhande PLC’s die communiceren met een Smartlock. Deze Smartlock is het brein dat onder andere bepaalt welke spoorwegwissels, … mogen gebruikt worden. Deze Smartlock bevindt zich niet in een keet, maar in de computerzaal. Hier wordt in hoofdstuk vier verder over uitgebreid en de betekenis van elke component wordt daar duidelijker. Zoals eerder vermeld krijgt de keet een voeding van 1 kV AC. In het tractieonderstation zal een omzetting met behulp van een transformator gebeuren. De transformatie gaat echter van 36 kV AC naar 11 of 12 kV AC. De transformatie van deze 11 (of 12) kV AC naar 1 kV AC zal verder in een hoogspanningspost gebeuren (met een tussenstap van 400 V AC). Deze weg die doorlopen wordt, wordt eveneens in hoofdstuk vier gedetailleerder uitgelegd. Het vermelden van het bestaan van de keten in dit hoofdstuk dient louter om aan te tonen dat het tractieonderstation niet alleen zorgt voor de voeding van de bovenleiding en dat zijn functionaliteit dus uitgebreider is.
10
1.4
Bepaling van het treinverbruik
1.4.1 Methodes Het treinverbruik wordt op twee verschillende manieren bepaald. De eerste manier is een schatting op basis van de graaddagen, de treinmassa (inclusief goederen of passagiers) en de lengte van het traject. De tweede manier is het gebruik van energiemeters die periodiek (dit kan per meter apart ingesteld worden) hun energieverbruik of –teruggave (remenergie) en gps-coördinaten met tijdstip doorsturen. Meestal wordt ingesteld dat er vanaf een bepaald tijdstip om het uur de gegevens worden doorgezonden. De meter neemt elke vijf minuten zijn gebruik of teruggave met positie en tijdstip op. Er wordt dan om het uur dus een verzameling van deze vijf minuten-waarden doorgestuurd. Het uur daarop wordt een volgende verzameling van gegevens naar Erex doorgestuurd. Erex wordt later nog uitgelegd. Het ligt hier voor de hand dat de gegevens van de energiemeters het meest nauwkeurig zijn en zij genieten dus de voorkeur. Het al dan niet gebruiken van de gegevens van de energiemeters wordt bepaald aan de hand van validatieregels. Hier wordt later nog meer uitleg over gegeven. 1.4.2 Schatting De schatting gebeurt op basis van formules die verschillen naargelang de categorie. In 2012 zagen deze formules er als volgt uit: Reizigerstrein:
(32 + 0,023 * D1 + 0,033 * D2) Wh/(ton*km)
Hogesnelheidstrein:
(40 + 0,023 * D1 + 0,033 * D2) Wh/(ton*km)
Goederentrein:
18 Wh/(ton*km)
De constanten in deze formules kunnen jaarlijks wijzigen. D1 en D2 in bovenstaande formules staan voor de graaddagen gebaseerd op de gemiddelde dagtemperatuur in Brussel. Bij D1 staat elke graad onder 16,5 °C voor één graaddag. D1 is de som van alle graaddagen in één maand. D2 wordt analoog berekend, maar hier is elke graad boven 20°C één graaddag. Deze graaddagen worden in rekening gebracht omdat het verbruik van de tractie-energie ook dient voor de airco of verwarming en deze zijn afhankelijk van de temperatuur buiten. 1.4.3 Meters Op onderstaande afbeeldingen worden een meter, aanwezig op een trein, en zijn stroom- en spanningsmeting weergegeven.
11
Figuur 5: Energiemeter (links) en zijn stroom- en spanningsmeting (rechts)
De energiemeter meet elke vijf minuten zijn energie op basis van zijn stroom- en spanningsmeting. Dit kan eveneens uit de eenheid Joule (J) afgeleid worden:
Een energiemeter geeft het exacte verbruik van een trein, terwijl een schatting niet steeds honderd procent correct zal zijn. Daarom geniet het gebruik van de energiemetergegevens de voorkeur boven de schattingen. In hoofdstuk vier worden de energiemeters verder uitgediept. 1.4.4 Eress en Erex Eress is een Europees partnerschap van spoorwegmaatschappijen van verschillende landen dat zich bezighoudt met de settlement van de tractie-energie. De partners hiervan zijn: Banedanmark (Denemarken), Jernbaneverket (Noorwegen), Trafikverket (Zweden), Liikennevirasto (Finland), Infrabel (België) en Groot-Brittannië. Eress werkt met een programma genaamd ‘Erex’. Erex is een Europese applicatie dat het mogelijk maakt om een zo juist mogelijke energiesettlement op te stellen. Op basis van deze settlement kan dan voor iedere klant een factuur opgesteld worden. Erex maakt gebruik van de gegevens afkomstig van de meters bij de trein aan boord aanwezig en gegevens zoals de massa, traject (detectiepunten), … die via IVET, een applicatie van Infrabel, worden doorgegeven. Met de gegevens afkomstig van IVET kan Erex dan een schatting van het 12
energieverbruik, die eerder al besproken werd, maken. Dit wordt in het volgende hoofdstuk verder besproken. Op onderstaande afbeelding wordt het logo van Eress en Erex weergegeven.
Figuur 6: Het logo van Eress en Erex (eress, z.j.)
13
Hoofdstuk 2: Huidige situatie en probleemstelling 2.1
Huidige situatie
2.1.1 Dataflow naar Erex
Figuur 7: Flow van gegevens naar Erex
In de bovenstaande afbeelding wordt de dataflow naar Erex weergegeven. Deze gegevens zijn nodig om tot een juiste facturatie te komen. IVET is een applicatie van Infrabel die uit verschillende databanken van Infrabel (bijvoorbeeld Martinis) de nodige gegevens voor Erex haalt en doorstuurt. Zo stuurt IVET voor de treinritten met vertrekdatum D-5 (als het vandaag 6 december is, stuurt hij de gegevens van 1 december door) dagelijks volgende gegevens door:
De spoorwegonderneming die met de trein rijdt De categorie (reizigers, HST of cargo) De doorrijtijden op verschillende detectiepunten, ook wel gekend als PTCAR’s De afstand tussen deze verschillende punten De massa De EVN (European Vehicle Number) of EVN’s van de tractie-eenheid of tractieeenheden
De graaddagen (de uitleg hierbij werd eerder al vermeld) worden manueel doorgestuurd naar Erex.
14
Met deze gegevens (IVET-gegevens en graaddagen) kan Erex zijn schatting op vlak van energieverbruik maken. De laatste vorm van gegevens krijgt Erex van de energiemeters die bij de treinen aan boord aanwezig zijn. Deze sturen periodiek (meestal om het uur) hun locatie met tijdstip en verbruik of teruggave naar Erex door. 2.1.2 Verwerking van deze gegevens aan de hand van validatieregels Het al of niet gebruiken van de doorgestuurde gegevens van de energiemeters wordt bepaald aan de hand van validatieregels. Enkele validatieregels zijn hieronder opgesomd.
Ligt de massa binnen de limieten? Komen de gemeten en de geschatte energie overeen? Komen de locatie en de tijd van de doorrijdpunten overeen met de gps-locaties en – tijdstippen van de meters? Is de afstand groter dan het geconfigureerde maximum? Is de afstand kleiner dan een rechte lijn? Bevindt de plaats zich binnen een geldig gebied? …
Al deze validatieregels en meer worden gecontroleerd binnenin Erex. In het kader van deze thesis doen slechts twee validatieregels er toe, namelijk als de gemeten en de geschatte energie overeenkomen en als de locatie en tijd van de doorrijdpunten (PTCAR’s) met de gpslocaties en –tijdstippen (energiemeters) overeenkomen. Indien niet voldaan is aan één van deze regels dan zullen de energiegegevens van de desbetreffende meter niet gebruikt worden. De schatting zal bijgevolg gebruikt worden om een settlement te maken.
2.2
Probleemstelling
Momenteel is slechts een fractie van de treinen voorzien van een energiemeter. Er worden dus nog veel treinritten gefactureerd op basis van een schatting. Het is echter de bedoeling dat in de toekomst alle treinen voorzien zullen zijn van een energiemeter. Wanneer nu een deel van de gegevens van de energiemeters de validatieregels niet doorstaat en dus een schatting voor de facturatie zal gebruikt worden, gaat dit dus slechts om een klein deel van het geheel aan treinritten. Wanneer alle treinritten echter voorzien zullen zijn van een of meerdere energiemeters, dan zal dit aantal veel hoger liggen. Aangezien men de juiste prijs aan elke klant wil aanrekenen, dient zoveel mogelijk de meetgegevens gebruikt te worden. De gegevens van de energiemeters geven namelijk het exacte en niet een geschat verbruik. De applicatie Erex moet dus uitgebreid worden zodat het aantal niet toegewezen energiegegevens afkomstig van de meters kleiner of zelfs onbestaand wordt. Dit laatste is het streefdoel.
15
Zowel Infrabel als Eress werken met databanken, maar deze werden niet ter beschikking gesteld voor deze thesis. Er werd echter gebruik gemaakt van Excel-bestanden die de gegevens bevatten van de databank van Eress (de databanken van Infrabel zijn hierin vervat want Infrabel stuurt haar gegevens door vanuit haar databanken). Aangezien het programma zo dicht mogelijk moet aanleunen bij het oorspronkelijke progamma Erex, dat in Java geschreven is, zal het programma in deze thesis eveneens in Java geschreven zijn. Wegens dezelfde reden zal met databanken gewerkt worden. Er dienen dus drie programma’s geschreven te worden: twee programma’s die de Excelbestanden omzetten naar een databank (één programma voor de gegevens van de meters en één programma voor de gegevens van de detectiepunten) en één hoofdprogramma dat de energieverbruiken van de meters toewijst aan de juiste treinrit (elke treinrit heeft zijn eigen treinritnummer).
16
Hoofdstuk 3: Algoritme 3.1
Oorzaken
Zoals eerder vermeld zijn er verschillende validatieregels waaraan de gegevens van de energiemeters en treinritten moeten voldoen. Voor deze thesis volstaat het enkel te kijken naar die meetgegevens die niet toegewezen zijn omwille van het niet overeenkomen van de detectiepunten en hun tijdstippen met de gps-coördinaten en -tijdstippen van de betreffende meter. Bijkomstig kan er ook gekeken worden of de gemeten energie overeenkomt met de geschatte energie en daar verdere conclusies uit getrokken worden. Er zijn verschillende oorzaken mogelijk waardoor de gegevens van de energiemeter niet voldoen aan de twee bovenvermelde validatieregels. Een eerste oorzaak is dat er manueel een fout werd ingevoerd die sowieso tot een foute schatting leidt. Zo kan bijvoorbeeld de verkeerde massa van de goederen bij een goederentrein ingevuld worden. In dit geval kan het probleem niet opgelost worden, tenzij dat de fout ingezien wordt en later manueel nog aangepast wordt. Een tweede oorzaak is dat het traject van de energiemeter totaal niet overeenkomt met het traject dat door de detectiepunten gedetecteerd is. In dit geval dient de meter toegewezen te worden aan een andere treinrit die nog niet over een toegewezen meter (‘empty’) beschikt. Dit kan zich bijvoorbeeld voordoen wanneer een meter werd gekoppeld aan een bepaalde treinrit, maar in werkelijkheid gebruikt werd in een andere treinrit. Erex controleert dus enkel de koppelingen van een meter en een treinritnummer die door Infrabel werden doorgegeven. Indien deze koppeling foutief is, wordt er niet zelf gezocht achter een nieuwe juiste koppeling. Het kan ook gebeuren dat het traject van de meter en de detectiepunten voor slechts een gedeelte overeenkomt. Dit kan zich bijvoorbeeld voordoen wanneer men tijdens het traject bijvoorbeeld de samenstelling verandert (een locomotief bijvoorbeeld toevoegen of verwijderen). In dit geval kan het overeenkomende gedeelte van het traject juist gefactureerd worden. Het overige gedeelte kan dan verder verwerkt worden door bijvoorbeeld een andere of een bijkomende meter te zoeken. Het is namelijk zo dat er in Erex momenteel een alles of niets regel geldt: indien het traject grotendeels klopt, dan zal dit gedeelte toch niet aan de meter toegewezen worden, waardoor correcte gegevens verloren gaan. Dit is de derde oorzaak. Een vierde oorzaak werd onrechtstreeks al in de vorige oorzaak vermeld. Het traject van een meter kan bijvoorbeeld overeenkomen met het traject van de detectiepunten, maar toch afgewezen worden omdat de gemeten energie niet overeenkomt met de geschatte energie. Wanneer er bijvoorbeeld ingegeven werd dat een bepaalde treinrit werkt met één locomotief, terwijl er in werkelijkheid twee werden gebruikt, dan zal Erex de gegevens van de meter niet aan deze treinrit toevoegen. Er moet dus een manier in het programma worden voorzien dat hiermee rekening houdt. 17
3.2
Algoritmes
Op basis van deze oorzaken kunnen enkel algoritmes opgesteld worden die de problemen moeten verhelpen. Vooraleer er overgegaan wordt naar de algoritmes volgt er een kleine samenvatting van hetgeen reeds bekend is. 3.2.1 Samenvatting De energieopname of –teruggave van de treinen gegeven door de energiemeters is nauwkeuriger dan een schatting. Om het gebruik van deze gegevens van de meters toe te laten, moeten aan een aantal validatieregels voldaan worden. Deze thesis houdt zich enkel bezig met de twee volgende validatieregels:
Is there a match between the payload and the metered locations? Is there a match between the payload and the metered energy?
Als aan de eerste validatieregel niet voldaan is, dan betekent dit dat de posities en/of tijdstippen van het traject gevormd door het doorrijden van de detectiepunten (ook wel PTCAR’s genoemd) niet overeenkomen met de doorgezonden posities en tijdstippen van de energiemeters. Als aan de tweede validatieregel niet voldaan is, dan houdt dit in dat er bijvoorbeeld twee locomotieven aan de treinrit meededen terwijl er slechts één van de twee opgegeven werd. Hierdoor zal de geschatte energie en de gemeten energie binnen bepaalde grenzen niet overeenkomen. Om toch tot een koppeling te komen tussen de niet toegewezen energiemeters (die dus samen met een treinrit niet voldoen aan één van de validatieregels) en een treinrit, worden voor deze meters enkele programma’s geschreven. Deze programma’s zullen trachten een koppeling te zoeken tussen een niet toegewezen energiemeter en één of meerdere treinritten, zodat toch de data van de meters en dus niet een schatting kunnen gebruikt worden. Wanneer bij het oplossen van problemen bij de eerste validatieregel een treinrit gevonden wordt, dan kan dit dezelfde treinrit zijn waarmee de meter oorspronkelijk verbonden was. Maar het kan hier bijvoorbeeld om slechts een deeltraject van de treinrit gaan waaraan de meter heeft meegedaan. Het kan ook voorkomen dat een andere treinrit gevonden wordt en dat de verbinding treinrit - meter die oorspronkelijk was ingegeven dus foutief is. Het oplossen van problemen bij de tweede validatieregel kan leiden tot het vinden van twee locomotieven (en dus twee meters), terwijl er bijvoorbeeld maar één was opgegeven bij een bepaalde treinrit. Dit werd daarnet al besproken. Zoals uit de tekst hierboven al blijkt, worden treinritten gekoppeld aan meters. Deze worden vervolgens gecontroleerd door Erex. Wanneer niet voldaan is aan één van de validatieregels dan wordt een schatting gebruikt. Er wordt dus binnenin Erex geen rekening gehouden met bijvoorbeeld een foutieve koppeling tussen een treinrit en een meter (bijvoorbeeld een spoorwegmedewerker die het verkeerd heeft ingegeven). Dit kan in de toekomst tot een groot 18
verlies aan correcte gemeten energie lijden aangezien steeds meer treinen met een energiemeter zullen uitgerust worden. Vooraleer de programma’s geprogrammeerd kunnen worden, moeten er algoritmes opgesteld worden. Deze algoritmes worden hieronder afgebeeld en uitgelegd. Het gaat om drie algoritmes: een algemeen overzicht, een algoritme voor de eerste validatieregel en een algoritme voor de tweede validatieregel. 3.2.2 Algemeen overzicht De inputs van Erex, die in het kader van deze thesis een belangrijke rol spelen, zijn de energiemeters en hun verzonden posities en tijdstippen en de detectiepunten waarlangs de treinen rijden (meer uitleg hierover komt in hoofdstuk 4 aan bod). De energiemeters zijn aanwezig op treinen en dus bij een treinrit continu in beweging. De detectiepunten zijn vaste punten waarlangs de treinen rijden. Als een trein zo’n punt passeert, dan is het tijdstip hiervan gekend. De positie van elk detectiepunt is eveneens gekend aangezien het vaste punten zijn. De energiemeters zenden periodiek (meestal om het uur) hun gegevens door naar Erex waar ze opgeslagen worden in een databank. De gegevens van de detectiepunten worden eerst in de databank van Infrabel opgeslagen. De applicatie IVET zendt dagelijks deze gegevens door naar Erex. In Erex worden beide gegevens vervolgens met elkaar vergeleken aan de hand van validatieregels. Bijvoorbeeld bij de validatieregel ‘Do payload and metered locations match?’ zal de data van de energiemeter gebruikt worden als het traject van deze meter overeenkomt met het traject van de treinrit (combinatie van meerdere detectiepunten) die verbonden werd met deze meter. De tijdstippen moeten uiteraard ook overeenkomen. In Erex kan vervolgens een lijst per validatieregel opgevraagd worden. Deze lijst bevat de meters die niet konden toegewezen worden aan een bepaalde treinrit. Voor deze meters zullen enkele programma’s geschreven worden zodat een koppeling met een treinrit (al dan niet de oorspronkelijke treinrit) gevonden kan worden. Aangezien de databanken van Infrabel en Erex niet rechtstreeks ter beschikking stonden voor deze thesis, werden er gegevens uit deze databanken opgevraagd. Deze werden in Excelformaat bezorgd. De data van de energiemeters werd opgevraagd uit de databank van Eress, terwijl de gegevens van de PTCAR’s uit een databank van Infrabel werden opgevraagd. Deze gegevens van de detectiepunten zijn ook aanwezig in de databank van Eress aangezien Infrabel deze gegevens dagelijks doorstuurt. Ze werden echter opgevraagd uit de databank van Infrabel omdat Erex deze gegevens niet in een Excel-formaat kon leveren. Om toch zo dicht mogelijk bij de werkelijkheid aan te leunen, werd een eigen databank aangemaakt. Twee programma’s zullen zich bezighouden met het aanmaken van deze databank en het daarnaar toe verplaatsen van de Excel-gegevens. Er wordt met de gegevens van de dag 25 september 2013 gewerkt. In de databank zal elke energiemeter zijn eigen tabel hebben. De gegevens van de detectiepunten en de treinritnummers worden allemaal in eenzelfde tabel opgeslagen. De
19
gegevens van de PTCAR’s (of TMS-data of Traffic Management System data) en de data van de meters bevinden zich dus in dezelfde databank, maar in verschillende tabellen. Nadat de invoer van de Excel-gegevens voltooid is, kan een vergelijking tussen beide soort gegevens gedaan worden. Het hoofdprogramma houdt zich hiermee bezig. Dit alles wordt hieronder afgebeeld. Hierin staan de kleuren voor de volgende programma’s:
Groen: programma dat de Excel-gegevens van de energiemeters van één dag in de databank zet. Rood: programma dat de Excel-gegevens van de detectiepunten en treinritten van één dag in de databank zet. Paars: programma dat deze twee soort gegevens met elkaar vergelijkt en kandidaatcombinaties (meter - treinritnummer) maakt (het hoofdprogramma).
Figuur 8: Algoritme met het algemeen overzicht
Het principe achter het hoofdprogramma wordt hierna uitgelegd.
20
3.2.3 Algoritme van het hoofdprogramma voor de eerste validatieregel Het algoritme dat hieronder wordt afgebeeld, houdt zich bezig met het koppelen van energiemeters aan treinritten wanneer niet voldaan is aan de eerste validatieregel of dus: Payload and metered locations did not match. Dit betekent dat het traject van beide soort gegevens (meter en detectiepunten) niet overeenkwam. Er worden naar andere kandidaat-koppels gezocht. De stappen van het algoritme zijn de volgende. 1. Er wordt vertrokken van de energiemeters, waarvoor de oorspronkelijke koppeling van energiemeter en treinritnummer deze validatieregel niet doorstond. 2. Er wordt om beurt met slechts één energiemeter gewerkt. 3. Het eerste element (combinatie van gegevens: tijdstip, posities, …) van deze meter wordt vergeleken met het eerste element van de TMS-data. 4. Vervolgens wordt dezelfde vergelijking gedaan, maar nu met het tweede element van de TMS-data. 5. Dit wordt herhaald totdat het eerste element van deze meter met alle gegevens van de PTCAR’s vergeleken is. 6. Vervolgens wordt hetzelfde gedaan voor het tweede element van de meter. 7. Dit wordt eveneens herhaald met de resterende elementen van de meter totdat de volledige meter vergeleken is met de gegevens van de detectiepunten. 8. Nadat de vergelijking van een meter met de TMS-data voltooid is, kan hetzelfde gedaan worden voor de volgende meter totdat alle meters die geen koppeling hadden, doorlopen zijn. 9. Wanneer er een vergelijking gebeurt en er een mogelijke match is, dan wordt deze in een extra kolom opgeslagen in de tabel van de desbetreffende energiemeter. 10. Merk hierbij op dat alle treinritnummers en hun trajecten in één tabel zitten, terwijl elke energiemeter zijn eigen tabel heeft. De vergelijking tussen beide soort gegevens wordt gedaan op twee vlakken, namelijk tijd en positie. Het verzonden tijdstip van de meter moet gelegen zijn tussen de twee activeringstijdstippen van de detectiepunten. Voor de posities wordt er een extra speling ingevoerd. Het kan namelijk voorkomen dat een traject tussen twee detectiepunten een nogal kromme vorm heeft. Er wordt gecontroleerd of de positie van de energiemeter zich in de rechthoek, gevormd door de twee detectiepunten, bevindt. In de afbeelding die op onderstaand algoritme is bijgevoegd, valt op dat er geen koppeling zal gemaakt worden terwijl deze koppeling wel correct zou zijn. Daarom wordt er een speling toegevoegd die de detectierechthoek groter maakt. Op deze manier kunnen meer kandidaat-voorstellen gemaakt worden. Meer uitleg hierover wordt eveneens bij de programmacode in hoofdstuk 6 gegeven. De posities zijn bij beide soort gegevens coördinaten met een breedte- en lengteligging (latitude en longitude), hier werd in de code eveneens rekening mee gehouden. In de tabel van de energiemeters zijn twee posities aanwezig, namelijk de begin- en eindpositie van het traject dat de energiemeter de afgelopen vijf minuten heeft afgelegd. Voor de vergelijking tussen de 21
positie van de energiemeter en de posities van de twee detectiepunten wordt met de eindpositie van de meter gewerkt. Deze eindpositie komt namelijk overeen met het tijdstip van het opslaan van de energiegegevens.
22
Figuur 9: Algoritme bij 'Payload and metered locations did not match'
23
3.2.4 Algoritme van het hoofdprogramma voor de tweede validatieregel Bij de validatieregel ‘Do payload and metered energy match?’ wordt er zoals eerder al vermeld de geschatte energie met de gemeten energie vergeleken. Als beide binnen bepaalde grenzen overeenkomen, kan er een koppeling gemaakt worden tussen een treinrit en een meter. Onderstaand algoritme houdt zich bezig met de energiemeters die niet gekoppeld konden worden. Vooraleer beide soort gegevens vergeleken kunnen worden met elkaar, moet er gekeken worden of de gemeten energie kleiner is dan 0,35 maal de geschatte energie (deze factor werd binnenin Infrabel bepaald en kan naargelang de nood veranderd worden). Indien dit zo is dan kan dit betekenen dat er bijvoorbeeld twee locomotieven in de treinrit aanwezig waren terwijl er maar één locomotief bij de treinrit was ingegeven. Deze locomotieven kunnen beide voorzien zijn van een meter of slechts één locomotief kan voorzien zijn van een meter. In dit laatste geval moet het verbruik van deze meter maal twee gedaan worden. In het eerste geval kunnen de energiegegevens van beide meters doorgefactureerd worden naar de klant. Indien niet aan deze voorwaarde (de 0,35-regel) voldaan is, dan kan er niet verder naar een mogelijke combinatie meter – treinrit gezocht worden. Als aan de voorwaarde voldaan is, kan het vergelijken starten. Het principe hierachter is hetzelfde als bij het algoritme van de eerste validatieregel, namelijk kijken of de positie en tijdstippen van beide soort gegevens overeenkomen. Het verschil hierin is dat er vertrokken wordt van een bepaalde treinrit en deze treinrit vergeleken wordt met alle energiemeters (daarnet werd er vertrokken van een beperkt aantal niet toegewezen energiemeters die vergeleken werden met alle treinritten). De stappen die doorlopen worden zijn op het algoritme weergegeven. Doordat de gemeten en de geschatte energie niet ter beschikking stonden, werd er geen programma bij deze validatieregel gemaakt. Het principe hierachter is echter analoog als bij het geschreven hoofdprogramma in hoofdstuk 6. Er zouden echter enkele kleine aanpassingen moeten gebeuren, bijvoorbeeld voor het opslaan van de gegevens van één treinrit in plaats van alle treinritten.
24
Figuur 10: Algoritme bij 'Payload and metered energy did not match'
25
Hoofdstuk 4: Input Zoals al eerder in deze thesis vermeld, worden de gegevens, afkomstig van de energiemeters, vergeleken met de TMS-data (gegevens afkomstig van de detectiepunten of PTCAR’s). Erex houdt zich hiermee bezig. Onder de detectiepunten hebben we twee middelen, namelijk assentellers en spoorstroomkringen (afgekort SK’s). Deze laatste kan verder opgesplitst worden in gewone spoorstroomkringen en jade spoorstroomkringen. In dit hoofdstuk worden de assentellers, spoorstroomkringen en energiemeters uitgelegd. Zij vormen als het ware de input van het programma Erex. Hoe de verbinding van de detectiepunten naar de server gebeurt, komt eveneens aan bod. Tenslotte wordt nog een algemeen beeld gegeven van alle componenten die een bijdrage leveren aan het opstellen van de energie-settlement.
4.1
Assentellers
Een assenteller zendt een magnetische signaal uit en bevindt zich aan weerskanten van een rail van een spoorweg. Wanneer een wiel (en dus een as) ter hoogte komt van deze assenteller, dan zal dit metalen wiel dit magnetisch veld beïnvloeden. Deze verandering wordt waargenomen en doorgegeven. Er wordt een onderscheid gemaakt tussen twee onderdelen van de assenteller, namelijk het detectiesysteem en het telsysteem. Het detectiesysteem vormt de doortocht van de treinwielen om in elektrische impulsen. Deze impulsen worden in het telsysteem omgezet in telwaarden. Er wordt steeds gebruik gemaakt van een combinatie van twee assentellers. De ene assenteller telt hoeveel wielen er binnenkomen en de andere telt hoeveel er buitengaan. Als het verschil hiervan nul is, dan is het spoor terug vrij, zo niet dan is het spoor bezet. Belangrijk bij het gebruik van de assentellers is dus het waarnemen of de trein toekomt of vertrekt. Elk detectiepunt beschikt daarom over minstens twee sensoren die op een bepaalde afstand van elkaar geplaatst zijn. Deze twee sensoren worden kort achter elkaar geactiveerd, maar niet tezelfdertijd. Op basis van de volgorde van deze twee activeringen kan de rijzin geconstateerd worden. Het principe hierachter wordt op onderstaande afbeelding nog eens weergegeven.
26
Figuur 11: Het bepalen van de rijzin bij assentellers (Van Hoyweghen, 2004)
27
Op onderstaande afbeelding wordt het detectieprincipe van de assenteller weergegeven. Hier is duidelijk te zien dat door de aanwezigheid van het metalen wiel het magnetisch veld veranderd wordt en dus detectie mogelijk gemaakt wordt.
Figuur 12: Detectieprincipe van de assenteller (Toelichting 15, 1998)
Op onderstaande afbeelding wordt het principe duidelijk gemaakt van hoe twee assentellers met elkaar gecombineerd worden. De logica hierachter bevindt zich in de assentellerkast binnenin de keet. Zoals op de afbeelding duidelijk is weergegeven, zijn er overlappen tussen de verschillende combinaties. 28
Figuur 13: Principe achter de combinatie van twee assentellers
Een nadeel van assentellers is dat de detectie intermitterend en dus niet continu werkt. Wanneer er bijvoorbeeld een stroomuitval heeft plaatsgevonden, dan weet de assenteller niet of er een trein aanwezig is. Deze detectie zal pas mogelijk zijn wanneer de assenteller terug geactiveerd wordt. Hier moet extra rekening mee gehouden worden naar beveiliging toe. Op onderstaande afbeelding wordt een assenteller weergegeven.
Figuur 14: Assenteller aan een rail in de nabijheid van het station Gent Sint-Pieters
29
4.2
Spoorstroomkringen
Bij spoorstroomkringen worden de sporen in verschillende secties gedeeld. Deze secties zijn elektrisch van elkaar gescheiden. Bij de gewone spoorstroomkringen wordt de scheiding tussen deze secties bekomen door isolaties in de rails toe te voegen. Deze isolaties worden ook wel voegen genoemd. Dit is op onderstaande afbeelding weergegeven.
Figuur 15: Verschillende secties en isolaties bij gewone SK's
Bij de jade spoorstroomkringen is het gebruik van deze isolatie niet meer nodig. Er wordt nog steeds een elektrische scheiding bekomen, maar ditmaal door een elektrische voeg. Het principe hierachter wordt later uiteengezet. 4.2.1 Gewone spoorstroomkringen 4.2.1.1 Circuit van de stroom Wanneer een trein, gevoed op 3 kV DC, rijdt dan moet de stroomtoevoer steeds een gesloten circuit vormen. Dit wordt op onderstaande afbeelding weergegeven.
30
Figuur 16: Distributie van tractiestroom (Module 0.1, 2010)
De stroom gaat dus van de transformator (36 kV AC / 3 kV AC) en gelijkrichter (3 kV AC / 3 kV DC) in het tractieonderstation over de bovenleiding, door de trein heen en langs de rails terug naar het tractieonderstation. Dit is het gesloten circuit van de stroom. Bij een gewone spoorstroomkring is er echter geen sprake van een gesloten circuit daar er isolaties in de rails geplaatst zijn. Deze isolaties dienen voor het creëren van verschillende detectiezones. Voor een gesloten circuit te bekomen, is er echter wel een oplossing. Er wordt gebruik gemaakt van twee spoelen met middenaftakking. Deze worden op onderstaande figuur weergegeven.
31
Figuur 17: Overbruggen van de isolaties
Een spoel vormt voor gelijkstroom een kortsluiting. Een trein die gevoed is op gelijkstroom zal zijn gesloten circuit alsnog kunnen vinden door de verbinding die gemaakt is tussen de middenaftakkingen van de spoelen. Op onderstaande afbeelding wordt het gebruik van zo’n spoel weergegeven.
32
Figuur 18: Gebruik van een spoel in de nabijheid van het station Gent Sint-Pieters
4.2.1.2 Werkingsprincipe Op onderstaande afbeelding wordt het principe van de gewone spoorstroomkring weergegeven. Deze spoorstroomkringen werken op wisselspanning en met een frequentie van 50 Hz. Het geheel bestaat uit een zender en ontvanger. Wanneer er geen trein op de sporen van de desbetreffende spoorstroomkring aanwezig is, dan zal het signaal van zender naar ontvanger verzonden worden. De ontvanger zal dan aangeven dat het spoor vrij is. Dit alles is in de bovenste helft van de afbeelding weergegeven. Wanneer nu echter een trein aanwezig is, dan zal de stroom steeds de makkelijkste weg volgen en dit is in dit geval langs de wielen van de trein. Het signaal van de zender wordt via de wielen als het ware kortgesloten en bereikt nooit zijn ontvanger. Het spoor is dus bezet. In theorie zal er nog een minieme stroom naar de ontvanger gaan, maar deze is niet groot genoeg. De werking van dit principe is eveneens goed ontworpen op vlak van veiligheid. Wanneer er bijvoorbeeld een stroomonderbreking is, dan zal de ontvanger ook geen signaal ontvangen en is het spoor als het ware bezet. Daar er bij een stroomonderbreking geen zekerheid is over de aanwezigheid van een trein, is het aangeven van een bezet spoor – al dan niet overeenkomend met de werkelijkheid – de veiligste signalering.
33
Figuur 19: Principe van een gewone spoorstroomkring (Toelichting 5, z.j.)
4.2.1.3 Geheel van gesloten stroomcircuit en spoorstroomkring Op onderstaande afbeelding wordt het volledige gesloten stroomcircuit, dat bekomen wordt dankzij de overbrugging via de middenaftakkingen van de twee spoelen, weergegeven. Het spreekt voor zich dat indien men verder gaat en dus meer isolaties tegenkomt, deze terug perfect overbrugd kunnen worden met behulp van meerdere spoelen. Voor de duidelijkheid werd de afbeelding van nummers voorzien om het verloop van het stroomcircuit aan te tonen.
34
Figuur 20: Geheel van gesloten stroomcircuit en spoorstroomkring
In elke sectie, gevormd tussen twee paar isolaties, zal een zender en ontvanger van de spoorstroomkring werkzaam zijn op 50 Hz. Dit is op bovenstaande afbeelding eveneens weergegeven. Het principe van de gewone spoorstroomkring met isolaties in elke rail, zoals hier voorgaand werd uitgelegd, wordt Birail spoorstroomkringen genoemd. Er bestaan ook Monorail spoorstroomkringen met slechts isolatie in één rail. Hier mag de geïsoleerde spoorstaaf geen deel uitmaken van de terugstroomkring. De Monorail spoorstroomkringen worden echter bijna niet meer gebruikt. Het gebruik van de Birail spoorstroomkringen is ook aan het verminderen en wordt meer en meer vervangen door jade spoorstroomkringen. Dit komt in het volgende stuk aan bod. 4.2.2 Jade of toonfrequente spoorstroomkringen 4.2.2.1 Algemeen Bij jade spoorstroomkringen wordt er geen gebruik gemaakt van isolaties in de rail. Dit heeft vooral op vlak van onderhoud een groot voordeel. De isolaties moeten namelijk niet onderhouden en vervangen worden, wat het prijskaartje op lange termijn doet dalen. Jade spoorstroomkringen kunnen ook bij hogesnelheidstreinen gebruikt worden, die niet op gelijkspanning maar op wisselspanning rijden. Dit is nog een extra voordeel. De tractiestroom kan nu ook zonder problemen langs het spoor zijn weg terug naar het tractieonderstation vinden. Er dienen hier dus geen overbruggingen met behulp van spoelen te gebeuren. Jade spoorstroomkringen werken nog steeds met een zender, ontvanger en het spoor als transmissielijn, maar met variabele frequenties (de gewone spoorstroomkringen werken met 50 Hz). De gebruikte frequenties voor jade spoorstroomkringen zijn: 1600 Hz, 1900 Hz, 2200 35
Hz en 2500 Hz. Er wordt wederom met secties of zones gewerkt die nu niet door de isolaties, maar door elektrische voegen bekomen worden. Deze elektrische voegen zorgen ervoor dat de elektrische signalen niet van de ene naar de andere zone kunnen overgaan. Om elektrische voegen te begrijpen, dient eerst serieresonantie en parallelresonantie uitgelegd te worden. 4.2.2.2 Serieresonantie Serieresonantie geschiedt door de combinatie van de zelfinductie van bijvoorbeeld een spoorrail of een koperdraad met een capaciteit die hiermee in serie is geschakeld. De resonantie ontstaat door de faseverschuiving bij beide componenten. Bij de condensator is er sprake van een capacitieve faseverschuiving. Hierdoor ijlt de stroom 90 graden voor op de spanning bij de condensator. De zelfinductie zal een inductieve faseverschuiving kennen. De stroom ijlt hierbij 90 graden na op de spanning. Ten opzichte van de stroom zal de spanning bij de condensator en de zelfinductie dus tegengesteld zijn aan elkaar. Serieresonantie treedt nu op bij die frequentie waarbij deze twee tegengestelde spanningen even groot zijn en elkaar dus opheffen. De resulterende impedantie van de kring is dan de weerstand bijvoorbeeld afkomstig van de koperdraden. Het gaat dus om een heel kleine weerstand. Door serieresonantie treedt er dus een kortsluiting op. Op onderstaande afbeelding worden de componenten van de serieresonantie weergegeven, met C1 de condensator, L1 de zelfinductie en R1 bijvoorbeeld de weerstand van de koperdraden.
Figuur 21: Serieresonantie (Basis elektronica deel 5, 2011)
De resonantiefrequentie bij serieresonantie bedraagt:
Op onderstaande grafiek wordt de stroomsterkte in functie van de frequentie bij een serieschakeling weergegeven. Bij de resonantiefrequentie (f0) treedt de grootste stroom op (serieresonantie). Bij een minieme weerstand van bijvoorbeeld de koperdraden komt deze grootste stroom dus overeen met een kortsluiting.
36
Figuur 22: Stroomsterkte in functie van de frequentie bij serieresonantie (Resonantiegedrag, 2010)
4.2.2.3 Parallelresonantie De opstelling van de parallelresonantie wordt op onderstaande afbeelding weergegeven.
Figuur 23: Parallelresonantie (Basis elektronica deel 5, 2011)
De resonantie ontstaat hier opnieuw door de faseverschuiving bij de zelfinductie en de condensator. Bij de zelfinductie zal de stroom 90 graden na-ijlen op de spanning en bij de condensator ijlt de stroom 90 graden voor op de spanning. Bij de frequentie waar deze twee stromen even groot zijn en elkaar dus opheffen (door hun tegengesteldheid) treedt parallelresonantie op. Hierdoor worden L1 en C1 als het ware een open keten. In het afgebeelde circuit is er nog een weerstand, die de resonantiefrequentie niet beïnvloedt, aanwezig. Deze weerstand is de impedantie bij de resonantiefrequentie. Bij de spoorwegen is deze theoretische weerstand niet aanwezig en bekomt men als het ware een volledige open keten. De resonantiefrequentie bij parallelresonantie is analoog aan die bij serieresonantie, namelijk:
Op onderstaande grafieken wordt het verloop van de impedantie, stroom en faseverschuiving in functie van de frequentie bij een serie- en parallelschakeling weergegeven en dit voor de volgende resonantiefrequenties: 1600 Hz en 2200 Hz. De minimale stroom gebeurt bij de
37
parallelschakeling inderdaad bij de resonantiefrequentie. Indien de weerstand onbestaand is, zal deze stroom nul ampère zijn of dus een open keten. Het Excel-bestand waarin deze grafieken gemaakt werden, kan op de bijgevoegde cd terug gevonden worden. Op onderstaande grafieken wordt serieresonantie bij 2200 Hz weergegeven. Er werd gewerkt met een weerstandswaarde van 10 Ω, een zelfinductie van 0,01 H, een condensatorwaarde van 5,23 . 10-7 F en een aangelegde spanning van 230 V.
Impedantie in functie van de frequentie (serieresonantie bij 2200 Hz) 1500
Z[]
1000 500 0 0
1000
2000
3000
4000
5000
6000
7000
f [ Hz ]
Figuur 24: Serieresonantie bij 2200 Hz (impedantie)
Stroom in functie van de frequentie (serieresonantie bij 2200 Hz) 25
I[A]
20 15 10 5 0 0
1000
2000
3000
4000
5000
6000
7000
f [ Hz ]
Figuur 25: Serieresonantie bij 2200 Hz (stroom)
38
Faseverschuiving in functie van frequentie (serieresonantie bij 2200 Hz) 100
[°]
50 0 0
1000
2000
3000
4000
5000
6000
7000
-50 -100
f [ Hz ]
Figuur 26: Serieresonantie bij 2200 Hz (faseverschuiving)
Op onderstaande grafieken wordt serieresonantie bij 1600 Hz weergegeven. Er werd hier gewerkt met een weerstandswaarde van 10 Ω, een zelfinductie van 0,019 H, een condensatorwaarde van 5,23 . 10-7 F en een aangelegde spanning van 230 V.
Impedantie in functie van de frequentie (serieresonantie bij 1600 Hz) 2000
Z []
1500
1000 500 0 0
1000
2000
3000
4000
5000
6000
7000
f [ Hz ]
Figuur 27: Serieresonantie bij 1600 Hz (impedantie)
39
Stroom in functie van de frequentie (serieresonantie bij 1600 Hz) 25
I [A]
20 15 10 5 0 0
1000
2000
3000
4000
5000
6000
7000
f [ Hz ]
Figuur 28: Serieresonantie bij 1600 Hz (stroom)
Faseverschuiving in functie van frequentie (serieresonantie bij 1600 Hz) 100
[°]
50 0 0
1000
2000
3000
4000
5000
6000
7000
-50 -100
f [ Hz ]
Figuur 29: Serieresonantie bij 1600 Hz (faseverschuiving)
Op onderstaande grafieken wordt parallelresonantie bij 2200 Hz weergegeven. Er werd gewerkt met een weerstandswaarde van 30000 Ω (dit moet dus de open keten benaderen), een zelfinductie van 0,01 H, een condensatorwaarde van 5,23 . 10 -7 F en een aangelegde spanning van 230 V.
40
Impedantie in functie van de frequentie (parallelresonantie bij 2200 Hz) 40000
Z[]
30000 20000 10000 0 -10000
0
1000
2000
3000 4000 f [ Hz ]
5000
6000
7000
Figuur 30: Parallelresonantie bij 2200 Hz (impedantie)
Stroom in functie van de frequentie (parallelresonantie bij 2200 Hz) 20
I[A]
15 10 5 0 0
1000
2000
3000
4000
5000
6000
7000
f [ Hz ]
Figuur 31: Parallelresonantie bij 2200 Hz (stroom)
41
Faseverschuiving in functie van frequentie (parallelresonantie bij 2200 Hz) 150 100 [°]
50 0 -50 0
1000
2000
3000
4000
5000
6000
7000
-100 -150
f [ Hz ]
Figuur 32: Parallelresonantie bij 2200 Hz (faseverschuiving)
Op onderstaande grafieken wordt parallelresonantie bij 1600 Hz weergegeven. Er werd gewerkt met een weerstandswaarde van 30000 Ω (dit moet dus de open keten benaderen), een zelfinductie van 0,019 H, een condensatorwaarde van 5,23 . 10 -7 F en een aangelegde spanning van 230 V.
Impedantie in functie van de frequentie (parallelresonantie bij 1600 Hz) 40000
Z[]
30000 20000 10000 0 -10000
0
1000
2000
3000
4000
5000
6000
7000
f [ Hz ]
Figuur 33: Parallelresonantie bij 1600 Hz (impedantie)
42
I[A]
Stroom in functie van de frequentie (parallelresonantie bij 1600 Hz) 14 12 10 8 6 4 2 0 0
1000
2000
3000
4000
5000
6000
7000
f [ Hz ]
Figuur 34: Parallelresonantie bij 1600 Hz (stroom)
Faseverschuiving in functie van de frequentie (parallelresonantie bij 1600 Hz) 150 100 [°]
50 0 -50 0
1000
2000
3000
4000
5000
6000
7000
-100 -150
f [ Hz ]
Figuur 35: Parallelresonantie bij 1600 Hz (faseverschuiving)
4.2.2.4 Vormen van een blokkeerfilter op basis van de resonantiefrequentie Op onderstaande afbeelding wordt een fragment van twee sporen in De Pinte weergegeven. Hetgeen in het groen omkaderd is, stelt een elektrische voeg voor. De afstand tussen TX en RX van zo’n voeg bedraagt steeds 30 meter.
43
Figuur 36: Schema van twee sporen in De Pinte
Eerst wordt er naar de rode rechthoek gekeken. Ter hoogte van TX25/19 wordt het signaal (afkomstig van de keet) verzonden en dit signaal wordt ter hoogte van RX25/19 ontvangen (bij afwezigheid van een trein). De zender en ontvanger zitten in de keet en worden van daaruit respectievelijk met de sporen verbonden ter hoogte van TX25/19 en RX25/19. Het principe van zenden en ontvangen is analoog als bij de gewone spoorstroomkringen (de ontvanger ontvangt een signaal bij de afwezigheid van een trein en bij de aanwezigheid van een trein wordt het signaal van de zender kortgesloten waardoor de ontvanger niets ontvangt). Het signaal dat tussen TX25/19 en RX25/19 loopt, werkt op 2500 Hz en verloopt volgens een bepaalde code, namelijk CD. Deze code wordt na de frequentie tussen haakjes weergegeven. Een overzicht van deze codes wordt hieronder op de bijgevoegde figuur weergegeven.
44
Figuur 37: Codes bij de jade spoorstroomkringen (Toelichting 5 bundel 5, 2001)
Op onderstaande afbeelding wordt een algemeen overzicht van een jade spoorstroomkring met zender en ontvanger vanuit de keet weergegeven.
45
Figuur 38: Algemeen overzicht van een jade spoorstroomkring met zender en ontvanger (Toelichting 5 bundel 5, 2001)
Het verzonden signaal, afkomstig van de keet, komt op het spoor terecht door middel van een transformator die zich in de serieresonantiekring van een spoorfilter bevindt. Dit spoorfilter wordt een zenderspoorfilter genoemd. Het ontvangen signaal wordt afgenomen van het spoor en hiervoor wordt een banddoorlaatfilter, die afgestemd is op de nominale frequentie van de jade spoorstroomkring, gebruikt. Deze filter wordt samen met een transformator (deze bevindt zich in het RX-blokje getekend op de afbeelding) parallel op de spoorfilter, ditmaal de ontvangerspoorfilter, geplaatst. De transformatoren die zich in de zenderspoorfilter en in de ontvangerspoorfilter bevinden, maken een galvanische scheiding met het spoor mogelijk. Op de afbeelding met de twee sporen in De Pinte staat TX19/25 voor een zenderspoorfilter (T: transmit) die een equivalente condensator (EC) voor 1900 Hz en een kortsluiting (SC) voor 2500 Hz vormt. RX25/19 is een ontvangerspoorfilter (R: receive) die een equivalente condensator voor 2500 Hz en een kortsluiting voor 1900 Hz vormt. Hoe deze filters met hun equivalente condensator (EC) en kortsluiting (SC) gevormd worden, wordt hierna uitgelegd. Nu wordt terug de groene rechthoek beschouwd en in verband gebracht met onderstaande afbeelding. TX19/25 komt hierbij overeen met Spoorfilter 1 en RX25/19 komt overeen met Spoorfilter 2. Tussen deze twee componenten bevindt zich 30 meter aan sporen. Deze sporen
46
beschikken over een zelfinductie. Deze zelfinductie is eveneens op onderstaande afbeelding voorgesteld. De spoel Ls2 en de condensator Cs2, die zich in de tweede spoorfilter bevinden, zijn zodanig ingesteld om met de frequentie f1 te werken. Deze spoel en condensator staan in serie en zullen dus bij de resonantiefrequentie f1 serieresonantie ondergaan. Dit komt overeen met een equivalente kortsluiting (SC) voor TFSK1. TFSK staat hierbij voor toonfrequentiespoorstroomkring en is een andere benaming voor de jade spoorstroomkring. De componenten in spoorfilter 1 vormen voor de frequentie f1 een equivalente condensator (EC) en deze equivalente condensator zal met de equivalente kortsluiting in spoorfilter 2 en de zelfinductie van het spoor parallelresonantie ondergaan. Door deze parallelresonantie wordt een blokkeerfilter gevormd voor de frequentie f1.
Figuur 39: Schema van de spoorfilters (Toelichting 5 bundel 5, 2001)
Dit blokkeerfilter, afgestemd op f1, wordt hieronder nog eens schematisch voorgesteld met zijn equivalente componenten.
Figuur 40: Blokkeerfilter afgestemd op f1 (Toelichting 5 bundel 5, 2001)
47
Dit principe kan herhaald worden, maar dan in tegengestelde richting om zo een blokkeerfilter te bekomen die afgestemd is op f2. Dit wordt op onderstaande afbeelding weergegeven. Deze blokkeerfilter komt overeen met de groene rechthoek. De TFSK2 is hierbij de 2500 Hz (CD). TX19/25 zal hierbij zorgen voor de equivalente kortsluiting bij een resonantiefrequentie van 2500 Hz en RX25/19 zal zorgen voor de equivalente condensator bij 2500 Hz. Tussen deze twee componenten wordt een blokkeerfilter gevormd voor de frequentie 2500 Hz. Deze zone wordt een elektrische voeg genoemd.
Figuur 41: Blokkeerfilter afgestemd op f2 (Toelichting 5 bundel 5, 2001)
Jade spoorstroomkringen hebben dus geen scherpe begrenzing. In het midden van de elektrische voeg is er namelijk een overlapping van de twee spoorstroomkringen. Buiten de elektrische voeg is de detectie steeds zeker; de elektrische voeg zorgt er namelijk voor dat de verschillende spoorstroomkringen elkaar niet kunnen beïnvloeden via de blokkeerfilters. Het frequentieverschil tussen twee opeenvolgende spoorstroomkringen wordt steeds groot genoeg genomen (in het voorbeeld van De Pinte bedraagt dit verschil 600 Hz). Er wordt dus gewerkt met een opeenvolging van afwisselende spoorstroomkringen, bijvoorbeeld 1900 Hz (EF), 2500 Hz (CD), 1900 Hz (AB), … Dit wordt op onderstaande afbeelding nog eens weergegeven voor dezelfde twee sporen van De Pinte, maar ditmaal voor een groter gebied.
48
Figuur 42: Schema van twee sporen in De Pinte (groter)
Merk op dat wanneer er na de tweede frequentie terug gebruik gemaakt wordt van de eerste frequentie, er een andere code gehanteerd wordt (bijvoorbeeld van 1900 Hz (EF) naar 1900 Hz (AB)). Dit is zodanig gedaan om beïnvloeding van dezelfde frequentie van een andere spoorstroomkring tegen te gaan als extra beveiliging. Op onderstaande afbeelding wordt een algemeen overzicht van de jade spoorstroomkringen (frequenties: 1600 Hz en 2200 Hz) weergegeven die bovenstaande uitleg over jade spoorstroomkringen samenvat. Bovenaan wordt de opbouw van de zender- en ontvangerspoorfilter samen met de zend- (Tx) en ontvangeenheid (Rx) (in de keet) weergegeven. Daaronder worden de corresponderende naamgevingen van deze filters getoond. Nog eens daaronder wordt de resonantiewerking weergegeven (equivalente condensator en kortsluiting), eerst voor 2200 Hz en daaronder voor 1600 Hz. De onderste twee delen van de afbeelding beslaan hetzelfde spoor, maar zijn opgesplitst getekend op basis van de frequentie voor de duidelijkheid. Op deze onderste twee delen van de afbeelding wordt in een rechthoek (gevormd tussen Tx en Rx van eenzelfde frequentie) steeds weergegeven met welke frequentie er gewerkt wordt. De kleine rechthoeken die geen 2200 Hz of 1600 Hz bevatten, zijn de elektrische voegen.
49
Figuur 43: Volledig overzicht van de jade spoorstroomkringen
50
4.3
Vergelijking van een spoorstroomkring en een assenteller
Op onderstaande tabel wordt ter informatie nog eens een overzicht van de vergelijking tussen een spoorstroomkring en een assenteller weergegeven.
Figuur 44: Vergelijking van een spoorstroomkring en een assenteller (Toelichting 5 bundel 7, 1996)
Op plaatsen waar de snelheid beperkt is tot 90 km/h mogen assentellers en spoorstroomkringen geplaatst worden. Bij snelheden groter dan 90 km/h moet een spoorstroomkring gebruikt worden. De reden hiervan is dat er bij spoorstroomkringen spoorstaafbreukdetectie is (zie ook bovenstaande tabel).
51
4.4
Energiemeters
In het eerste hoofdstuk kwamen energiemeters al kort aan bod. Hier worden deze nog verder uitgediept. In dat hoofdstuk werd al vermeld dat we voor de energie te meten we over een bepaalde tijd de spanning en stroom moeten meten. Dit principe wordt op onderstaande afbeelding weergegeven.
Figuur 45: Energiemeting (Jans, 2009)
Er wordt dus gebruik gemaakt van stroom- en spanningssensoren. Over een bepaalde tijd worden de stromen en spanningen gemeten en aldus kan de energie berekend worden. Dit wordt dan doorgestuurd en in het Data Handling System verder behandeld.
52
4.4.1 Ingangen van de energiemeter 4.4.1.1 Algemeen
Figuur 46: Overzicht van de energiemeting (Railway Current & Voltage Transducers, 2011)
Het is de bedoeling te werken met een energiemeter die zowel op gelijk- als op wisselspanning kan werken aangezien dit het gebruik ervan heel toepasbaar maakt bij treinen. Op bovenstaande afbeelding worden de inputs stroom en spanning, afkomstig van ofwel wisselspanning (25 kV AC) of gelijkspanning (3 kV DC), weergegeven. De wisselspanning en wisselstroom worden respectievelijk met een spanningstransformator en een stroomtransformator omgezet naar een spanning en stroom die bruikbaar is voor de energiemeter (centraal in de figuur: EM4T II). Bij gelijkspanning en gelijkstroom wordt er gebruik gemaakt van een spanning- en stroomomvormer om zo tot een geschikt signaal te komen dat de energiemeter kan gebruiken. 4.4.1.2 Spanningsomvormer Op onderstaande afbeelding wordt het blokschema van zo’n spanningsomvormer (op bovenstaande figuur is dit component DV 4200/SP4) weergegeven.
53
Figuur 47: Blokschema spanningsomvormer (DV series Voltage Transducer: Insulated High Voltage measurements, 2008)
Dit blokschema toont aan dat de hoge ingangsspanning via een netwerk van weerstanden naar een Sigma-Delta analog digital convertor gebracht wordt. Zoals de naam het doet vermoeden, zorgt deze voor een omzetting van een analoog naar een digitaal signaal. Deze Sigma-Delta convertor bestaat hier uit een convertor, een modulator, een transformator, een decoder en een digitaal filter. De modulator moduleert dit digitaal signaal (na de ADC) om zo een wisselspanningssignaal van de bitstream te bekomen. Dit wordt dan door een scheidingstransformator verzonden. Op deze manier ontstaat er een fysische scheiding. Vervolgens wordt het gemoduleerd signaal gedecodeerd alvorens te filteren (de decoder is niet op de afbeelding weergegeven). In het digitaal filter dat daarop volgt, wordt het signaal gefilterd (zie ook Excel-bestand op de cd-rom), waarna vervolgens in de microcontroller een digitaal analoog conversie plaatsvindt. Tenslotte wordt in de U/I generator een spanning-stroom omvorming gedaan. Op de bovenkant van de afbeelding wordt de voeding eveneens weergegeven (+V c en –Vc). 4.4.1.3 Stroomomvormer Op het overzicht van de energiemeting zien we dat voor de stroomomvorming de stroomomvormer ITC 2000-S gebruikt wordt. Deze werkt volgens het fluxgate principe. Dit principe wordt op onderstaande afbeelding getoond. De gelijkstroom die men wilt meten of primaire stroom is I1, de fluxgate-stroom is IF en de compensatiestroom of secundaire stroom is I2. De spanning (alternerende blokgolf) die over de fluxgate staat en de stroom die dit teweeg brengt wanneer er geen primaire stroom aanwezig is, zijn op de tweede hieronder staande afbeelding afgebeeld. De gemiddelde waarde van IF is dus 0 A. Wanneer er nu een primaire stroom aanwezig is, zal deze gemiddelde stroom toenemen of afnemen afhankelijk van de stroomrichting van deze primaire stroom. Dit is op de derde afbeelding hieronder getoond. Op basis van deze gemiddelde stroom zal I 2 bijgeregeld worden totdat de resulterende flux terug nul is.
54
Figuur 48: De fluxgate meet de resulterende flux (Pollefliet, 2011)
Figuur 49: Stroom en spanning in de fluxgate-spoel zonder primaire stroom (Pollefliet, 2011)
55
Figuur 50: Stroom en spanning in de fluxgate-spoel bij een primaire stroom (Pollefliet, 2011)
Bij deze secundaire spoel kan er een weerstand in serie geplaatst worden. Over deze weerstand kan dan een spanning, die representatief is voor de te meten stroom, gemeten worden. Dit fluxgate-principe met aansturing wordt op onderstaande afbeelding nog eens weergegeven.
Figuur 51: Fluxgate van LEM (Pollefliet, 2011)
56
In een laatste stadium, namelijk de output stage, wordt met behulp van een versterker het energieverbruik van de omzetter en zijn verliezen beperkt. Dankzij een filter worden de harmonischen eveneens beperkt. Een tweede manier om aan stroomomvorming te doen, kan met behulp van een shuntweerstand. Dit is eveneens op het overzicht van de energiemeting weergegeven. Hierbij plaatst men een weerstand in serie met de last (in dit geval de tractie-eenheid). Alle stroom gaat hierdoor en over deze weerstand kan men dan een spanning meten. De DI die op het overzicht is weergegeven, is een samenstelling van een shuntweerstand en een aangepaste spanningsomvormer. Deze tweede manier van stroomomvorming is echter minder nauwkeurig dan het fluxgate principe. 4.4.2 Meetprincipe van de energiemeter Bij de energiemeter worden de inputs (spanningen en stromen uit het vorige stuk) gedigitaliseerd. Met deze digitale signalen kan het energieverbruik berekend worden. Het blokschema van de energiemeter wordt hieronder weergegeven.
Figuur 52: Blokschema van de energiemeter (Jans, 2009)
Links op de afbeelding worden dus ofwel de gelijkspanning en –stroom ofwel de wisselspanning en –stroom (die naar een spanning of stroom bruikbaar voor de meter zijn omgezet) gelezen en vervolgens van analoog naar digitaal geconverteerd. In de CPU gebeurt het rekenwerk om tot het energieverbruik te komen. Deze data wordt in het flashgeheugen 57
bewaard. Het geheel wordt ofwel direct op 24 V DC gevoed ofwel op 110 V DC die vervolgens wordt omgezet naar 24 V DC (DC/DC omzetting). De analoog digitaal conversie, waar zonet sprake van was, is een sigma-delta ADC en gebeurt met een bemonsteringsfrequentie van 4 kHz. Dit wordt in het volgende stuk verder besproken. 4.4.3 Conversies Vooraleer de sigma-delta conversie uitgediept wordt, worden eerst wat algemeenheden rond conversie verklaard. Een eerste aspect is de digitaal naar analoog conversie, daarna wordt analoog naar digitaal conversie uitgelegd met tenslotte wat meer toelichting over de sigma-delta conversie. 4.4.3.1 Digitaal analoog conversie (DAC) Een overzicht van deze conversie wordt op onderstaande afbeelding weergegeven.
Figuur 53: Digitaal analoog conversie (Jans, 2009)
De digitale signalen komen links op deze afbeelding binnen. Vervolgens worden ze gekoppeld en aangehouden (hold) aan een welbepaald spanningsniveau. Dit gebeurt zo voor elke digitale ingang en het resultaat kan in het midden van de figuur worden bekeken. Vervolgens wordt dit signaal, bestaande uit blokken, door een smoothing filter gestuurd om zo tot een mooi analoog signaal te komen (rechts van de figuur). 4.4.3.2 Analoog digitaal conversie (ADC) Een overzicht van deze conversie wordt op onderstaande afbeelding weergegeven.
58
Figuur 54: Analoog digitaal conversie (Jans, 2009)
Links van de figuur komt een analoog signaal binnen dat vervolgens sampling of bemonstering (bijvoorbeeld door vermenigvuldiging met een dirac-impuls) ondergaat. Bij sampling wordt periodiek een waarde van het analoog signaal genomen om zo tot de pijlen in het midden van de figuur te komen. Daarna volgt kwantisatie. Bij kwantisatie worden er digitale waarden gezocht die de amplitudes na sampling representeren. Bij analoog digitaal conversie moet aliasing voorkomen worden. Als er bij de analoog digitaal conversie niet frequent genoeg gesampled werd, dan kan het gebeuren dat bij de reconstructie van het signaal (DAC) niet het oorspronkelijke signaal, maar een ander signaal gereconstrueerd wordt. Dit wordt op onderstaande afbeelding weergegeven.
Figuur 55: Aliasing (Aliasing effects, z.j.)
Wanneer er gesampled werd zoals op de onderstaande helft van de bovenstaande afbeelding (de sampling is door de bolletjes voorgesteld), dan wordt bij de reconstructie niet het oorspronkelijke signaal bekomen, maar een signaal met een lagere frequentie. Wanneer er gesampled werd zoals op de bovenstaande helft van de afbeelding (de samplefrequentie is hier veel hoger), dan wordt het juiste signaal gereconstrueerd. Bij aliasing kan dus niet meer het oorspronkelijke signaal afgeleid worden. Om aliasing te vermijden, moet de bemonsteringsfrequentie minimaal tweemaal zo groot zijn als de hoogste frequentiecomponent in het te samplen signaal. Voor deze reden wordt het analoog signaal voor de conversie eerst nog door een 59
laagdoorlaatfilter, ook wel anti-aliasing filter genoemd, gestuurd. Deze filter filtert alle frequenties die groter zijn dan de nyquist-frequentie. De nyquist-frequentie is de helft van de bemonsteringsfrequentie. Uiteindelijk zal de analoog digitaal converter opgebouwd zijn zoals op onderstaande afbeelding.
Figuur 56: Opbouw ADC (Jans, 2009)
Hierbij staat LPF (Low Pass Filter) voor laagdoorlaatfilter (anti-aliasing filter). S&H staat voor Sample and Hold. Er wordt hier een hold toegevoegd omdat de conversie van analoog naar digitaal (kwantisatie) een welbepaalde tijd nodig heeft en daarom moet de waarde even vastgehouden worden (bijvoorbeeld door het gebruik van een condensator). In het blokje ADC wordt de kwantisatie uitgevoerd. Op onderstaande afbeelding wordt het principe achter Sample and Hold nog eens geïllustreerd. Wanneer de schakelaar ingeduwd wordt, dan wordt de samplewaarde bepaald. In de condensator wordt deze waarde bewaard.
60
Figuur 57: Sample & Hold (Jans, 2009)
Op onderstaande afbeelding wordt het samplen door middel van vermenigvuldiging met een dirac-impuls weergegeven.
Figuur 58: Samplen door middel van een dirac-impuls (Jans, 2009)
Een voorbeeld van kwantisatie kan teruggevonden op onderstaande figuur. Het gaat hier om een 3 bit analoog digitaal converter. Vx is de spanning die bekomen wordt na de Sample and Hold. Er wordt gebruik gemaakt van meerdere spanningsdelers en comparatoren. De spanning Vr zorgt via de verschillende spanningsdelers voor een referentiespanning voor elke comparator. De spanning Vx is verbonden met de plus van de comparator en de referentiespanning met de min van de comparator. Als de spanning V x groter is dan de referentiespanning dan geeft de comparator een 1-signaal. Zo niet wordt een 0-signaal
61
afgegeven. Op basis van de logica achter de comparatoren (EN-, OF- en NIET-poorten) bekomt men een binaire uitgang of binaire code.
Figuur 59: Voorbeeld van kwantisatie (Jans, 2009)
4.4.3.3 sigma-delta analoog digitaal conversie Bij deze vorm van conversie, die nog steeds een analoog signaal omzet naar een digitaal signaal, wordt bemonsterd aan een frequentie die groter is dan de nyquist-frequentie. Het voordeel hiervan is dat hoewel de kwantisatieruis dezelfde blijft, deze over een grotere frequentieband wordt verdeeld. Bij de kwantisatie wordt voor iedere analoge waarde een digitale waarde toegewezen. Deze koppeling is niet altijd perfect daar er maar een eindig aantal digitale waarden zijn tegenover een groot scala aan analoge waarden. De fout die hierbij ontstaat, wordt kwantisatieruis genoemd en is de fout tussen de analoge waarde en de digitale waarde na kwantisatie. Het nadeel dat hier tegenover staat, is dat het geheel complexer wordt (werken met meer bits, …). Een voorbeeld van een opbouw van deze convertor is hieronder afgebeeld. De flowchart dat daarbij hoort wordt daaronder eveneens getoond. Het gedeelte tussen de analoge ingang en de bitstream vormt de convertor. De bitstream wordt vervolgens doorgestuurd naar de decimator (digitaal filter). Deze decimator zorgt ervoor dat de seriële bitstream bekomen door de overbemonstering wordt omgezet naar een parallele weergave (N bits) hiervan. 62
Figuur 60: Principe van de sigma-delta ADC
B=C=D=E=0
A (analog input)
B = A - E(n-1)
C = B + C(n-1) Y
N C >= 0
D=1
D=0
E = +Uref
E = -Uref
volgende sample (fs)
Figuur 61: Flowchart van de sigma-delta ADC
Op de bijgevoegde cd-rom bevindt er zich een Excel-bestand dat deze werking simuleert.
63
4.4.4 Processor In de processor gebeurt al het rekenwerk. Hiervoor wordt een onderscheid gemaakt tussen wisselspanningvermogens en gelijkspanningvermogens. 4.4.41 Wisselspanningvermogens De klassieke formules voor het berekenen van het schijnbaar vermogen, het actief vermogen en het reactief vermogen zijn de volgende.
Door het nemen van samples zullen deze formules niet zomaar gebruikt kunnen worden. Er wordt gewerkt met het momentele vermogen:
Figuur 62: Dubbele frequentie van het vermogen ten opzichte van de spanning en de stroom
Aangezien het vermogen een dubbele frequentie heeft ten opzichte van de stroom en de spanning (dit wordt in bovenstaande afbeelding geïllustreerd), kan het actief vermogen van de energiemeter berekend worden door het gemiddelde van het momentele vermogen te nemen over een halve stroom- of spanningsperiode. Deze halve periode bedraagt dus 10 ms bij een 50 Hz frequentie. Volgende formule representeert dit.
64
De formule van het momentele vermogen kan hier ingevuld worden.
De stappen van de som tussen t = 0 en T/2 zijn de samplemomenten (bij dit type meter is dit 1 sample/ms of 10 samples bij 50 Hz want T/2 is dan gelijk aan 10 ms). Om het schijnbaar vermogen te vinden na sampling vertrekken we van de definitie hiervan.
De effectieve spanning- en stroomwaarden kunnen gehaald worden uit volgende formules.
Deze formules zouden geldig zijn indien er sprake was van een continu verloop, maar in dit geval werd er gesampled (n samples). Deze formules moeten dus omgevormd worden.
Indien deze formules nu toegepast worden op de definitie van het schijnbaar vermogen en er rekening gehouden wordt met de halve periode van het vermogen ten opzichte van de spanning en de stroom, dan wordt de volgende formule verwezenlijkt.
65
Het principe achter het berekenen van het schijnbaar vermogen wordt op onderstaande afbeelding duidelijk weergegeven. Nu dat het actief en het schijnbaar vermogen berekend zijn, is de berekening van het reactief vermogen makkelijk te vinden uit volgende formule.
Figuur 63: Principe van het berekenen van het schijnbaar vermogen
4.4.41 Gelijkspanningvermogens Bij gelijkspanning is er geen sprake van schijnbaar vermogen, actief vermogen en reactief vermogen. Er wordt daar enkel over vermogen gesproken. Op analoge wijze kan bij gelijkspanning het vermogen berekend worden. Dit gebeurt volgens onderstaande formule. Hierbij is T geen periode maar een gekozen tijdspanne (want bij DC is er geen periode). De tussenstappen van de som zijn terug de samplemomenten. Er kan terug voor T 10 ms gekozen worden met een samplemoment elke milliseconde.
66
4.4.5 Global positioning system Er werd al eerder vermeld dat de energiemeter naast zijn energieverbruik en tijdstippen ook zijn locaties met behulp van gps (global positioning system) doorstuurt. Daarom wordt hier kort over deze materie uitgeweid. De satellieten (zender) die voor gps-doeleinden gebruikt worden, sturen een signaal naar een ontvanger op de aarde (in dit geval bevindt deze zich op de trein). Dit signaal bevat onder andere het tijdstip van de verzending op basis van de atomische klokken en de locatie van de satelliet (deze locatie wordt uiteraard continu geüpdatet). De ontvanger bevat eveneens een interne klok en kan op basis van het tijdsverschil tussen zenden en ontvangen en de snelheid van het verzonden signaal (lichtsnelheid) berekenen op welke afstand deze satelliet zich van de ontvanger bevindt. Zo kan er als het ware een bol met als straal deze afstand rondom deze satelliet gecreëerd worden met alle mogelijke ontvangerposities. Als de ontvanger twee signalen ontvangt van twee verschillende satellieten, kan een tweede bol rondom deze tweede satelliet gecreëerd worden. De snijpunten van deze twee bollen geven een al meer exacte mogelijkheid van waar de ontvanger zich ergens bevindt. Op onderstaande afbeeldingen worden deze bollen rondom de twee satellieten en hun snijpunten (meer bepaald een ring) weergegeven.
Figuur 64: Bol rondom de satelliet (GPS, z.j.)
Figuur 65: Ring tussen twee satellietbollen (GPS, z.j.)
Indien nu een derde satelliet wordt toegevoegd, blijven er nog maar twee mogelijke punten over. Een van deze punten is meestal te verwerpen (bijvoorbeeld niet gelegen op de aarde, …) en zo bekomt men de uiteindelijke positie. Dit principe is op onderstaande afbeelding weergegeven.
67
Figuur 66: Twee mogelijke punten op basis van gps (GPS, z.j.)
Indien nog meer satellieten worden toegevoegd, bekomt men een steeds preciezere positiebepaling, maar het werken met drie satellieten is al voldoende. Voor een tweedimensionale positiebepaling voldoen drie satellieten, indien de hoogte ook gekend wilt zijn, dient men te werken met een minimum van vier satellieten. De banen van de satellieten zijn zodanig opgesteld dat er op een willekeurige plek op aarde steeds een minimum aan vijf satellieten voor de ontvanger bereikbaar zijn. De satellieten bevinden zich op ongeveer 20000 km hoogte ten opzichte van de aarde.
4.5
Globaal beeld: energie- en informatieflow
Nu alle inputs verklaard zijn, kan een globaal beeld van het werkgebied van deze thesis geschetst worden. Op onderstaande afbeelding wordt niet alleen de energieflow naar de treinen, maar ook deze naar de inputs zoals assentellers en spoorstroomkringen weergegeven. Er wordt vertrokken van het hoogspanningsnet (bijvoorbeeld door een aansluiting op het 36 kV AC net van Elia). Het tractieonderstation is hiermee verbonden. Deze hoogspanning wordt gebruikt voor drie doeleinden, namelijk de voeding van de “normale” treinen (zowel passagiers- als goederentreinen), de hogesnelheidstreinen (TGV) en de voeding van onder andere de keten, de computerzaal, … De “normale” treinen rijden op 3 kV DC en er dient dus niet alleen een transformatie van 36 kV AC naar 3 kV AC te gebeuren, maar ook een gelijkrichting van deze laatste. De hogesnelheidstreinen rijden op 25 kV AC, een transformatie van 36 kV AC naar 25 kV AC voldoet hier dus. Tenslotte wordt de 36 kV AC getransformeerd naar 11 kV AC of 12 kV AC (afhankelijk van de plaats: Gent werkt bijvoorbeeld met 12 kV AC, terwijl Brugge en Brussel met 11 kV AC werken). Deze laatste spanning van 11 of 12 kV AC wordt vervolgens in de hoogspanningspost gebruikt. Daar wordt deze naar beneden getransformeerd, namelijk naar 400 V AC. Deze spanning kan dan gebruikt worden voor de computers in de computerzaal (waar de EBP, stratus en smartlock/SSI’s zich bevinden, maar daar later meer over). Deze 400 V AC spanning wordt eveneens getransformeerd naar 1 kV AC. De keten langs de spoorwegen werken op deze spanning. In deze keten gebeuren nog verdere transformaties die in de afbeelding zijn weergegeven. Dit is afhankelijk van de functie van de keten en meerdere spanningen kunnen in eenzelfde keet voorkomen. Deze in de keet omgevormde spanningen worden dan bijvoorbeeld gebruikt voor de voeding van de assentellers, de 68
spoorstroomkringen en de verlichting die zich buiten de keet bevinden of voor de voeding van bijvoorbeeld de PLP’s die zich in de keet bevinden. De uitleg over PLP’s volgt hierna.
Figuur 67: Energieflow
Op onderstaande afbeelding wordt de informatieflow die naar Erex vloeit weergegeven.
69
Figuur 68: Informatieflow naar Erex
70
Het begin van de informatie is uiteraard afkomstig van de treinen. Dit houdt onder andere zijn traject, energieverbruik, … in. Dit kan opgesplitst worden in twee delen, namelijk de data afkomstig van de energiemeters die zich op de treinen bevinden en direct naar Erex worden verstuurd en de data afkomstig van de detectiepunten (assentellers en spoorstroomkringen) die nog een parcour moeten afleggen eer bij Erex aan te komen. Dit parcour gaat van de assenteller (via de assentellerkast) of de spoorstroomkring naar een PLP in de keet, om vervolgens naar een SSI of Smartlock te gaan in een computerzaal. Vandaar gaat de informatie verder naar de EBP en de stratus (eveneens in een computerzaal) om uiteindelijk op een server van Infrabel te landen en verzonden te worden naar Erex. Al deze tussenstappen worden hieronder kort uitgelegd. De Stratus is de centrale computer van de EBP. Deze Stratus bevat een programma dat zich bezighoudt met de veiligheid naar reiswegen van treinen toe. Zo zal hij kijken of bijvoorbeeld twee aangelegd reiswegen elkaar niet storen. EBP staat voor Elektronische BedieningsPost. In principe zijn alle reiswegen op voorhand aangelegd. De EBP bestaat uit een aantal computers die manueel bediend worden. Daar worden de geplande reiswegen goedgekeurd of gewijzigd door de computeroperatoren. Wanneer er bijvoorbeeld vertraging is en twee geplande reiswegen met elkaar zouden overlappen, dan moet een wijziging in één van deze aangelegde reiswegen doorgevoerd worden. De Stratus berekent vervolgens als dit wel mogelijk is. Wanneer een trein een bepaald traject moet afleggen, moeten er allerlei zaken aangestuurd worden: signalen moeten gegeven worden, wissels moeten verplaatst worden, … Daarom is er communicatie nodig van de Stratus naar de buitenwereld toe. De SSI (Solid State Interlocking) of Smartlock zorgt hiervoor. Een Smartlock is een moderne variant van de SSI en kan in principe beschouwd worden als meerdere SSI’s in één apparaat. In de toekomst zullen alle SSI’s vervangen worden door Smartlocks. Een SSI of Smartlock staat dus in contact met de buitenwereld en zorgt ook voor de veiligheid hierbij. Afhankelijk van de reisweg zal de Smartlock of SSI naar de PLP’s in de keten sturen welke signalen (bijvoorbeeld groene lamp wanneer de trein mag rijden, …) en acties (bijvoorbeeld verplaatsen van een wissel, …) er moeten getoond en ondernomen worden. De PLP’s zorgen ervoor dat dit gebeurt en geven informatie terug aan de Smartlock of SSI (bijvoorbeeld de wissel staat links, …). De Smartlock communiceert dan terug met de Stratus en de EBP. Het gaat dus om een tweerichtingsverkeer. PLP staat voor Poste à Logique Programmée en is een soort veiligheidsPLC. Deze PLP wordt ingesteld door paramaterkaarten, die zich eveneens in de keet bevinden. Zoals hierboven reeds werd uitgelegd, stuurt de PLP bijvoorbeeld de wissels en signalering aan wanneer de Smartlock of SSI dit eist. De PLP stuurt ook informatie terug naar de Smartlock of SSI. De verbinding tussen SSI/Smartlock en PLP gebeurt met een optische vezelkabel. De volledige logica (spoorstroomkring/assenteller > PLP > SSI/Smartlock > …) werkt volgens de ‘fale safe’ logica. Er moet steeds een signaal aanwezig zijn voor het krijgen van een veilige toestand. Door de fale safe logica zal bij het ontbreken van dit signaal het spoor als bezet worden weergegeven. Dit ontbreken kan ofwel bekomen worden door de aanwezigheid van een trein of een technische storing. 71
In deze bezette toestand is het onmogelijk om nog reiswegen over het betreffende stuk aan te leggen. Een defect aan de installatie wordt dus ook geïnterpreteerd als een bezet spoor al dan niet strokend met de werkelijkheid. Dit is de veiligste manier van werken. Hieronder volgen nog enkele foto’s die enkele van deze componenten in de werkelijkheid weergeven.
Figuur 69: Voeding van een keet
72
Figuur 70: Verschillende PLP's in een keet
Figuur 71: Parameterkaarten van de PLP's
73
Figuur 72: Assentellerkast
74
Figuur 73: Elektriciteitskasten in een keet
Figuur 74: EBP
75
Figuur 75: SSI's
Figuur 76: Transformator (36 kV AC / 11 kV AC) in het tractieonderstation van Brussel-Zuid
76
Figuur 77: Kenplaat van deze transformator
77
Hoofdstuk 5: Excel, databanken en Java 5.1
Excel
Er wordt dus gewerkt met twee types Excel-bestanden. Het eerste type omvat alle gegevens omtrent de detectiepunten per dag en is afkomstig uit de database van Infrabel. Het tweede type omvat alle data van alle energiemeters per dag en is afkomstig van Erex. Beide bestanden zijn opgeslagen in de ‘.csv’ extensie en dienen in Excel via ‘Opslaan als’ in ‘.xlsx’ veranderd te worden om de werking met Java mogelijk te maken.
5.2
Databanken
De databanken worden in de programmeertaal SQL geschreven en er wordt gebruik gemaakt van het programma ‘MySQL Workbench’. Andere talen zijn mogelijk, net zoals andere programma’s, maar er werd voor dit gratis programma en deze taal gekozen. Iedere databanktoepassing kan onderverdeeld worden in de databank met zijn gegevens, een databankbeheerssysteem, ook wel gekend als database management system (DBMS) en een aantal toepassingprogramma’s. Deze toepassingprogramma’s, die gebruikt worden door de gebruikers, communiceren met het databankbeheerssysteem. Deze laatste staat in voor het beheer en de uitvoering van de toegang tot de database. Een DBMS beschikt onder andere over volgende faciliteiten:
‘Data Definition Language’ waarmee gebruikers gegevensstructuren kunnen omschrijven ‘Data Manipulation Language’ waarmee gebruikers gegevens kunnen opvragen, toevoegen, aanpassen of verwijderen ‘Query optimizer’ waarmee zo snel mogelijk en met zo weinig mogelijk geheugen het resultaat teweeg gebracht wordt …
De opbouw van zo een databanktoepassing wordt in de volgende afbeelding geïllustreerd.
78
Figuur 78: Opbouw van een databanktoepassing
De databank zorgt voor de opslag van allerlei gegevens en is dus een soort digitaal archief. Het is de bedoeling op ieder moment de bestaande gegevens te raadplegen, aan te passen of te verwijderen en zelfs nieuwe gegevens toe te voegen. De indelingen van de gegevens en de relaties tussen verschillende gegevens worden in de databank zelf opgeslagen als metadata. Het DBMS maakt gebruik van deze metadata om aanvragen van de toepassingsprogramma’s te verwerken. De metadata zijn dus data over data. Een databaseserver (één computer) beschikt over de DBMS en verwerkt de databank. Het zorgt ervoor dat de gebruikers (de clients) bij een bepaald dataverzoek de vereiste data terugkrijgen. Indien er sprake is van één server per databank en verscheidene clients, dan wordt dit het client-server model genoemd. Andere modellen met meerder servers zijn eveneens mogelijk, maar dan wordt het geheel wel complexer. Het client-server model wordt in onderstaande afbeelding geïllustreerd.
79
Figuur 79: Client-server model (Moreau, 2013)
Er wordt gewerkt met het relationele gegevensmodel en men spreekt bijgevolg van een relationele database management system (RDBMS). Het relationeel model is wiskundig gebaseerd op de verzamelingsleer en de predikatenlogica en is onafhankelijk van een specifieke RDBMS implementatie. Relationele tabellen (bestaande uit kolommen en rijen) zijn gemaakt volgens de eerste normaalvorm (1NF):
Elke rij is uniek en dus mogen geen twee rijen in een tabel gelijk zijn aan elkaar Alle gegevens in een kolom zijn hetzelfde datatype De gegevens van een tabel (dit is de doorsnede van een tabel en een rij) zijn enkelwaardig, de gegevens zijn dus enkele, atomaire waarden
Elke tabel beschikt over minstens één sleutel. Een sleutel is datgene wat elke rij in een tabel uniek maakt, dit hoeft niet enkelvoudig (één kolom) te zijn en kan dus even goed een combinatie zijn van verschillende kolommen. Er zijn verschillende vormen van sleutels. Kandidaat-sleutel Een kandidaat-sleutel is de combinatie van één of meerdere kolommen die elke rij in een tabel uniek maakt. Het is mogelijk dat er meerdere kandidaat-sleutels voorkomen. Kandidaatsleutels bestaan uit een primaire sleutel en eventuele alternatieve sleutels. Primaire sleutel De primaire sleutel is de uiteindelijke gekozen kandidaat-sleutel voor het uniek vastleggen van de rijen. 80
Alternatieve sleutel De alternatieve sleutel of sleutels zijn de kandidaat-sleutel of kandidaat-sleutels die overblijven na het kiezen van een primaire sleutel. Het spreekt voor zich dat als er maar één kandidaat-sleutel is, er enkel een primaire sleutel zal zijn en geen alternatieve sleutels. Er zijn nog andere normaalvormen (tweede tot vijfde normaalvorm) waaraan voldaan kan worden, maar deze zijn niet verplicht. Er dient steeds gekeken te worden welke normaalvormen best wel en welke best niet toegepast worden. Samengevat bestaat een databank dus uit één of meerdere tabellen. Tussen deze tabellen kan er al dan niet een relatie bestaan. In de ene tabel kunnen bijvoorbeeld de namen van de deelnemers, hun score en de bijhorende wedstrijden staan en in een andere tabel kunnen de deelnemers voorkomen met hun geboorteplaats en bijhorende nationaliteit. Er bestaat een relatie tussen deze twee tabellen en er kan een link gelegd worden met behulp van de deelnemers hun namen. Deze tabellen moeten sowieso voldoen aan de eerste normaalvorm en moeten over een primaire sleutel beschikken. De databanken werken eveneens volgens het client-server model waarbij er meerde clients gegevens (met behulp van queries) kunnen opvragen. De server handelt deze aanvragen verder af. 5.2.1 SQL SQL staat voor Structured Query Language en is een databasetaal. SQL is een transformatiegeörienteerde taal: de resultaten van het ondervragen van een aantal tabellen worden in tabelvorm weergegeven. SQL is een niet-procedurele of declaratieve taal, dit wil zeggen dat de gebruiker aangeeft welke gegevens hij wilt en niet de wijze waarop dit verwezenlijkt wordt. Een database bestaat uit één of meerdere tabellen. Zo kan een databank van een bibliotheek bestaan uit een tabel ‘klanten’, een tabel ‘boeken’, een tabel ‘uitgevers’ enzovoort. Om deze database en tabellen te creëren en aan te passen, maken we gebruik van de programmeertaal SQL. Enkele kernwoorden hierin zijn:
CREATE: een database of tabel maken INSERT: gegevens in een tabel toevoegen SELECT: selecteren van gegevens uit een tabel DROP: verwijderen van een tabel uit een database of een database in zijn geheel …
De datatypes die in SQL gebruikt worden, zijn onder andere:
INT: wordt gebruikt voor de opslag van gehele getallen FLOAT: wordt gebruikt voor de opslag van decimale getallen VARCHAR(x): wordt gebruikt voor de opslag van tekststrings met een maximum aantal tekens, die wordt vastgelegd door de gebruiker opgegeven waarde ‘x’ 81
DATETIME: wordt gebruikt voor de opslag van data en hun tijdstip op die dag …
Indien in een kolom geen waarde wordt mee gegeven, dan zal de waarde ‘NULL’ automatisch ingevuld worden. Zoals de naam het zelf doet vermoeden, staat dit voor een nul-waarde of een leegte. Dit mag niet verward worden met het cijfer nul, dit is namelijk wel een ingevulde waarde en is dus niet hetzelfde. Hieronder volgen enkele voorbeelden van hoe dit in MySQL Workbench te werk gaat. Dit zal eveneens wat meer duidelijkheid scheppen over de taal SQL. 5.2.2 Voorbeelden Bij het openen van MySQL Workbench verschijnt volgend scherm.
Figuur 80: Startscherm van MySQL Workbench
Voor verder te gaan, dient er op de ‘Local instance’ geduwd te worden en dient de server, die momenteel op inactief staat, gestart te worden. Dit gebeurt in het menu ‘Startup/Shutdown’. Dit wordt op onderstaande afbeelding weergegeven.
Figuur 81: Startup / Shutdown
82
In dit menu kan de server gestart worden door op ‘Start Server’ te duwen. Er dient tweemaal het wachtwoord opgegeven te worden. Dit wordt hieronder geïllustreerd
Figuur 82: Invullen van het wachtwoord
Hierna is de status van de database server veranderd. In de bovenstaande twee afbeeldingen ging de status van ‘stopped’ naar ‘starting’. Nadat de wachtwoorden correct zijn ingevuld zal de server de status ‘running’ weergeven. Dit kan ook op onderstaande afbeelding afgelezen worden.
Figuur 83: De running status van de database server
Nu de server ter beschikking staat, kan er in MySQL Workbench gewerkt worden. Als voorbeeld wordt eerst een databank gecreëerd. Via de menubalk kan een nieuwe databank (of schema zoals het hier wordt genoemd) aangemaakt worden. Deze menubalk wordt hieronder weergegeven.
Figuur 84: Menubalk van MySQL Workbench
Hierna dient een naam voor de nieuwe databank gekozen te worden. Ter illustratie wordt hier ‘voorbeeld_thesis’ gekozen. Dit is hieronder weergegeven. 83
Figuur 85: Invullen van de naam van de databank
Daarna wordt op ‘Apply’ geduwd en verschijnt een eerste voorbeeld van de taal SQL, namelijk “CREATE SCHEMA ‘voorbeeld_thesis’”. Dit is hieronder weergegeven.
Figuur 86: SQL bij het creëren van een databank
84
Nadat dit is doorgevoerd, kan bij het overzicht van de schema’s of databanken gezien worden dat deze nieuwe en lege databank is toegevoegd. Dit wordt hieronder afgebeeld.
Figuur 87: Voorbeeld_thesis is aan het overzicht toegevoegd
Door vervolgens deze databank in het menu te ontvouwen, kan bij het submenu ‘Tables’ de optie gekozen worden om een tabel aan te maken. Deze optie kan aangesproken worden door op het submenu met de rechter muisknop te klikken. Dit is hieronder weergegeven.
Figuur 88: Aanmaken van een tabel
Hierna verschijnt volgend scherm met de instellingen van de tabel. Als tabelnaam werd ‘bananen’ gekozen. De verschillende kolommen kunnen ook ingesteld worden. Het gaat hier om de id van de tabel die eveneens de primaire sleutel is, een kolom met de winkels waar de bananen verkocht worden en tenslotte een kolom die het aantal bananendozen besteld door deze winkel weergeeft. De datatypes worden hier ook gekozen.
85
Figuur 89: Instellingen van een tabel
Indien op ‘Apply’ geduwd wordt, dan wordt opnieuw de corresponderende SQL-code achter deze bewerking weergegeven.
Figuur 90: SQL-code achter het aanmaken van een tabel
Indien nu terug op het overzicht gekeken wordt, dan ziet dit eruit zoals op onderstaande afbeelding. Vaak moet eerst op de ‘refresh’-knop van dit overzicht geduwd worden voor het weergeven van de doorgevoerde veranderingen. Indien nu met de rechtermuisknop op bananen wordt geklikt en de optie ‘Select Rows’ geselecteerd wordt, dan verschijnt de tabel bananen. Deze is momenteel nog volledig leeg.
86
Figuur 91: Weergeven van de tabel bananen
Deze lege tabel wordt hieronder weergegeven. De SQL-code hierachter wordt eveneens weergegeven, namelijk: “SELECT * FROM voorbeeld_thesis.bananen”. Het sterretje staat hier voor alle gegevens in de tabel. Om de query uit te voeren dient op het bliksemschichtje geduwd te worden.
Figuur 92: De lege tabel bananen
Nu kunnen handmatig gegevens in deze tabel worden toegevoegd. Wanneer op ‘Apply’ geduwd wordt, dan verschijnt eveneens de SQL-code voor het invoeren van deze gegevens. Dit alles wordt hieronder afgebeeld.
87
Figuur 93: Invullen van de tabel en de SQL-code hierachter
Indien nu terug de SQL-code “SELECT * FROM voorbeeld_thesis.bananen” in een query zou uitgevoerd worden, dan zou de ingevulde tabel in plaats van een lege tabel weergegeven worden. De tabel ziet er nu uit zoals op onderstaande figuur.
Figuur 94: De ingevulde tabel bananen
Nu kunnen hier enkele queries op losgelaten worden, die de bovenstaande tabel aanpassen naar een andere tabel. Zo kan de gebruiker enkel wensen de eerste twee kolommen weer te geven met de volgende SQL-code: “SELECT idBananen, Winkel FROM voorbeeld_thesis.bananen”. Merk hierbij op dat de tabel bananen in principe onveranderd blijft, maar enkel een andere weergave ervan wordt tentoongesteld. De uitvoer van deze code is hieronder weergegeven.
88
Figuur 95: Selecteren van de eerste twee kolommen van de tabel
Op dezelfde manier kan de volgorde van de weergegeven kolommen veranderd worden. Een voorbeeld van een omgekeerde weergavevolgorde is dan: “SELECT Aantal, Winkel, idBananen FROM voorbeeld_thesis.bananen”. De gebruiker kan bijvoorbeeld een ordening van het hoogste naar het laagste aantal bestelde bananendozen willen. Een dergelijke uitvoer ziet er als volgt uit. Merk hierbij op dat er aan de code een order-clausule is toegevoegd, namelijk ‘ORDER BY’. ‘Desc’ staat hier voor dalende volgorde en ‘asc’ staat voor stijgende volgorde. Hier blijft de oorspronkelijk tabel terug onberoerd.
Figuur 96: Ordenen van de tabel
89
De leverancier kan bijvoorbeeld een promotie doorvoeren voor zijn grootste klanten. Dit zijn de klanten die meer dan twintig bananendozen besteld hebben. Om deze weer te geven kan hij een where-clausule aan zijn SQL-code toevoegen. De uitvoer hiervan wordt hieronder weergegeven.
Figuur 97: Gebruik van de where-clausule
Zoals uit bovenstaande code blijkt, is het combineren van meerdere clausules perfect mogelijk. Zo heeft de leverancier niet enkel zijn grootste klanten weergegeven, maar eveneens een ordening hierin van zijn minst grootste klant naar zijn allergrootste klant. Het gebruik van de select-opdrachten in een query beïnvloedt de oorspronkelijk tabel dus nooit, maar heeft enkel een weergave of een aangepaste weergave hiervan. De uitvoer is dus als het ware een tijdelijke tussentabel. Indien gebruik gemaakt wordt van ‘DROP’, ‘UPDATE’, ‘CREATE’, … worden wel aanpassingen doorgevoerd. Dit blijkt eveneens uit onderstaande voorbeelden. De leverancier begint bijvoorbeeld aan een nieuwe maand en er zijn momenteel nog geen bestelling doorgekomen. Daarom wilt hij alle aantallen op nul hebben. Volgende code verwezenlijkt dit. Deze code zal de oorspronkelijke tabel wel aanpassen.
Figuur 98: Het updaten van waarden in de tabel
Indien nu terug alle waarden van de tabel geselecteerd worden, dan is duidelijk te zien dat de tabel wel degelijk veranderd is. Dit is hieronder afgebeeld. 90
Figuur 99: De tabel na de update
Op dezelfde manier kunnen een of meerdere kolommen verwijderd of toegevoegd worden. Een volledige tabel kan zelfs verwijderd worden. De leverancier kan bijvoorbeeld beslissen om te stoppen met het leveren van bananendozen en heeft daardoor geen nood meer aan de tabel ‘bananen’. De code die hij hiervoor zal gebruiken, ziet er zo uit: “DROP TABLE voorbeeld_thesis.bananen”. Na het refreshen zal deze tabel niet meer worden weergegeven in het overzicht. Het spreekt voor zich dat de SQL-taal veel uitgebreider is dan de code die in deze kleine voorbeelden gedemonstreerd werd. Maar in het kader van deze thesis is het gebruik van deze gedemonstreerde code voldoende. Aangezien het handmatig creëren, invullen en aanpassen van databanken een tijdrovend werk is en het bij deze thesis gaat om een uitgebreid gamma aan gegevens, moeten deze databankverwerkingen automatisch gebeuren. Dit zal met behulp van de programmeertaal Java verwezenlijkt wordt. Een korte inleiding over Java wordt in het volgende stuk gegeven.
91
5.3
Java
In dit stuk van het hoofdstuk wordt er wat meer informatie over de programmeertaal Java gegeven. Java is een objectgeoriënteerde taal. Er werd voor deze taal gekozen aangezien het reeds bestaande programma Erex eveneens in deze taal geschreven is. Hetgeen hier neergeschreven staat, is slechts een fractie van de mogelijkheden die met Java bekomen kunnen worden, maar in het kader van deze thesis is dit voldoende. 5.3.1 Datatypes In het gedeelte over SQL werd al over datatypes gesproken. Het principe bij Java blijft hetzelfde, alleen de benamingen kunnen verschillen. Een overzicht van enkele datatypes in Java wordt hieronder weergegeven.
Primitieve datatypes voor gehele getallen o byte: beschikt over een opslagruimte van 1 byte o short: beschikt over een opslagruimte van 2 bytes o int: beschikt over een opslagruimte van 4 bytes (meestal wordt deze gebruikt voor het werken met gehele getallen) o long: beschikt over een opslagruimte van 8 bytes Primitieve datatypes voor getallen met vlottende komma (decimale getallen) o float: beschikt over een opslagruimte van 4 bytes o double: beschikt over een opslagruimte van 8 bytes Primitieve datatype voor karakters o char: beschikt over een opslagruimte van 2 bytes Primitief datatype voor logische veranderlijken (true of false) o boolean: beschikt over een opslagruimte van 1 byte
Een stukje tekst bestaat in principe uit een opeenvolging van meerdere karakters. In Java kan hiervoor de klasse String (vergelijkbaar met VARCHAR in SQL) gebruikt worden. Dit is geen primitief datatype omdat het bestaat uit meerdere karakters en dus verder opgedeeld kan worden. Het spreekt voor zich dat er bewerkingen op deze datatypes of Stringteksten kunnen uitgevoerd worden. Denk maar aan de klassieke rekenbewerkingen die op gehele of decimale getallen kunnen uitgevoerd worden (optelling +, aftrekken -, vermenigvulding *, …). Van Stringteksten kan onder andere de lengte of een karakter op een specifieke positie gevraagd worden. De mogelijkheden hierin zijn enorm en er wordt hier niet verder over uitgeweid. De bewerkingen die in deze thesis gebruikt worden, worden kort uitgelegd met de bijhorende code in het volgende hoofdstuk. 5.3.2 Controlestructuren Hieronder wordt een kort overzicht weergegeven van enkele controlestructuren in Java. Het gaat onder andere over het gebruik van lussen en iteraties.
92
5.3.2.1 de if-opdracht Bij de if-opdracht wordt er gekeken of er aan een bepaalde voorwaarde voldaan is. Indien aan deze voorwaarde voldaan is, wordt een bepaalde handeling uitgevoerd. Indien niet aan deze voorwaarde voldaan is, kan er een extra voorwaarde worden toegevoegd. Deze extra voorwaarde is dan een else-opdracht. Zo kan bijvoorbeeld een optelling gemaakt worden van het aantal meisjes en jongens. In de ifopdracht kan zo gevraagd geworden als de betreffende persoon een meisje is. Als dit zo is dan zal in de if-opdracht het aantal meisjes geïncrementeerd worden. Is de persoon geen meisje dan wordt overgegaan naar de else-opdracht waar het aantal jongens geïncrementeerd wordt. Een overzicht hiervan is hieronder weergegeven.
Figuur 100: Voorbeeld van een if-else-opdracht
In een ziekenhuis kan men bijvoorbeeld een optelling uitvoeren op de dienst geriatrie. Hierbij komen de patiënten met een leeftijd lager dan 70 jaar in categorie 1, patiënten met een leeftijd vanaf 70 jaar maar lager dan 80 jaar in categorie 2 en patiënten die een leeftijd hebben vanaf 80 jaar in categorie 3. Het spreekt voor zich dat hier de if-else-opdracht niet zal voldoen aangezien er meer dan twee mogelijkheden zijn. De if-else-opdracht kan uitgebreid worden met een ‘else if’. Het principe hiervan is hieronder afgebeeld. Het spreekt voor zich dat er nog verder uitgebreid kan worden door toevoeging van meerdere else if-opdrachten.
93
Figuur 101: Uitbreiding door een else if-opdracht
In code zou dit voor het laatste voorbeeld er als volgt uitzien: if (leeftijd < 70) {categorie1 ++;} else if (leeftijd >= 70 and leeftijd < 80) {categorie2++;} else {categorie3++;} Uit voorgaande code kan één van de bewerking teruggevonden worden waar eerder over gesproken werd, namelijk een optelling en meer specifiek een incrementatie: categorie1++ is het equivalent van categorie1 (nieuwe waarde) = categorie1 (oude waarde) +1 De if-opdracht (en zijn else-if- en else-componenten) kan in principe ook als een lus beschouwd worden, maar dan met slechts één iteratie. Daarom wordt in deze thesis soms naar de if-opdracht verwezen met het woord ‘if-lus’, ook als is het per definitie geen lus aangezien het niet meerdere malen doorlopen kan worden. Het beschikt echter wel over voorwaarden waaraan voldaan moeten zijn om de opdracht te voltooien. Dit is bij de andere lussen ook zo. 5.3.2.2 De for-lus Bij het gebruik van de for-lus ligt het aantal iteraties vast. De lus wordt een aantal maal doorlopen en nadat dit aantal bereikt wordt, zal het programma verder gaan met de code na de 94
lus. Zo kan men met een for-lus gemakkelijk de natuurlijke getallen van 0 tot 20 afbeelden. Schematisch ziet dit er als volgt uit.
Figuur 102: Afbeelden van de natuurlijke getallen 0 tot 20 met behulp van een for-lus
De code die hiermee correspondeert is: for (int i = 0 (startvoorwaarde); i <= 20 (werkvoorwaarde van de lus); i++ (handeling aan het einde van de lus)) {System.out.println(i);} Met ‘System.out.println()’ kunnen teksten als output van het programma weergegeven worden. Hier worden dus telkens op een nieuwe lijn de natuurlijke getallen van 0 tot 20 weergegeven. 5.3.2.3 de while-lus en de do-while-lus In de while-lus wordt de lus uitgevoerd zolang aan de logische voorwaarde voldaan is. Hier gaat het dus niet om een vast aantal iteraties. De do-while-lus werkt volgens hetzelfde principe, maar hier wordt pas op het einde gekeken als aan de voorwaarde voldaan is. Het gevolg hiervan is dat de lus sowieso eenmaal doorlopen wordt. Indien dus in het begin niet aan de voorwaarde voldaan is, dan zal de while-lus nul iteraties kennen en de do-while-lus één iteratie. Onderstaand codevoorbeeld illustreert dit het best. Deze code toont een volledig programma zoals het ook in Eclipse (de applicatie waarin geprogrammeerd werd) zou voorkomen. import java.io.*; public class While {
95
public static void main(String[] args) throws IOException { InputStreamReader isr = new InputStreamReader (System.in); BufferedReader in = new BufferedReader (isr); System.out.println("-------------------------------"); System.out.println("while-lus:"); System.out.println("-------------------------------"); System.out.println("Geef tekst in: "); String tekst = in.readLine(); while(tekst.charAt(0) == '1' && tekst.charAt(1) == '9' && tekst.length() == 4) { System.out.println(">>>>>>Jaartal: " + tekst); System.out.println("Geef tekst in: "); tekst = in.readLine(); } System.out.println("-------------------------------"); System.out.println("do-while-lus:"); System.out.println("-------------------------------"); System.out.println("Geef tekst in: "); String tekst2 = in.readLine(); do { System.out.println(">>>>>>Jaartal: " + tekst2); System.out.println("Geef tekst in: "); tekst2 = in.readLine(); } while(tekst2.charAt(0) == '1' && tekst2.charAt(1) == '9' && tekst2.length() == 4); } }
In deze code wordt eerst de ‘java.io’-package ingeladen. Hierdoor kan er met inputs en outputs gewerkt worden (bijvoorbeeld het invoeren van tekst via het klavier). Er is eveneens een klasse met de naam ‘While’ aangemaakt die de code bevat. De ‘InputStreamReader’ en ‘BufferedReader’ zijn eveneens nodig voor input via het klavier toe te laten. Daarna wordt een while-lus gedemonstreerd. Er wordt gevraagd een jaartal op te geven en indien dit jaar met 19 begint (dit wordt gecontroleerd met behulp van ‘charAt(x)’ die een karakter op een bepaalde positie ‘x’ in een Stringtekst weergeeft), dan zal dit jaartal als output verschijnen, indien niet wordt er overgegaan naar de resterende code. Met behulp van ‘in.readLine()’ kan tekst ingegeven met het computerklavier worden ingelezen. Hierna volgt de do-while-lus. Indien hier een jaartal dat niet met 19 begint wordt ingevuld, zal dit toch afgebeeld worden. Pas na de eerste iteratie zal het stoppen van de lus bekomen kunnen worden door een jaartal in te vullen dat niet met 19 begint. De input en output van deze code wordt hieronder afgebeeld.
96
Figuur 103: Werking van een while- en do-while-lus
Het is uiteraard mogelijk lussen met elkaar te combineren. In een for-lus kan perfect een if-lus uitgevoerd worden. Indien lussen in andere lussen worden gebruikt, dan spreekt men van geneste lussen. 5.3.3 Methodes Een Java-programma werkt steeds met een hoofdmodule. Dit wordt gekenmerkt door het woord ‘main’. In de vorige code over de while-lus en de do-while-lus was er enkel een hoofdmodule (public static void main …) aanwezig. Het is mogelijk om in plaats van alle code in deze module te zetten en zo tot een complex geheel te komen, te werken met methodes. Methodes kunnen door de hoofdmodule opgeroepen worden. Soms wordt er bij het oproepen van deze methodes enkele parameters meegegeven (bijvoorbeeld een geheel getal). Deze methodes kunnen dan iets teruggeven aan de hoofdmodule, maar dit is niet vereist. In onderstaande code wordt een getal ingegeven. De hoofdmodule roept een eerste methode op die dit getal als parameter heeft meegekregen en een halvering hierop toepast. De gehalveerde waarde van dit getal wordt vervolgens terug meegegeven aan de hoofdmodule. Hierna roept de hoofdmodule een tweede methode op met als meegegeven parameter de gehalveerde waarde. Deze tweede methode drukt deze waarde af. Deze module geeft niets terug aan de hoofdmodule. Tenslotte roept de hoofdmodule een derde methode op die het einde van het programma aankondigt. Hier wordt geen parameter meegegeven en de derde methode geeft ook niets terug. Nadat de methode voltooid is, wordt terug naar de hoofdmodule gegaan en eindigt het programma. De code die dit principe toont, heeft volgende weergave. import java.io.*; public class Methodes { public static void main(String[] args) throws IOException {
97
InputStreamReader isr = new InputStreamReader (System.in); BufferedReader in = new BufferedReader (isr); System.out.println("------------------------"); System.out.println("Methodes:"); System.out.println("------------------------"); System.out.println("Geef getal op: "); double getal = Double.parseDouble(in.readLine()); double helft = methode1_halveren(getal); methode2_weergeven(helft); methode3_einde(); System.out.println("Er wordt steeds naar de hoofdmodule teruggegaan.");
} static double methode1_halveren (double getal) { double helft = getal/2; return helft; } static void methode2_weergeven (double helft) { System.out.println("Module2: " + helft); } static void methode3_einde () { System.out.println("Module3: Einde"); } }
De uitvoer van deze code is de volgende.
Figuur 104: Werking van methodes
Het gebruik van methodes is handig om de complexiteit van een programma te verminderen. Wanneer een bepaalde handeling (bijvoorbeeld het berekenen van de oppervlakte of het zoeken van de minimale afstand tussen twee punten) veelvuldig moet uitgevoerd worden in een programma, is het handiger met methodes te werken. Deze methode moet slechts eenmaal geprogrammeerd worden en kan steeds opnieuw opgevraagd worden. Afhankelijk van de 98
eventueel meegegeven paramaters zal de methode een andere uitvoer hebben. Het gebruik van parameters is niet verplicht en de methode is ook niet verplicht iets terug te geven aan de hoofdmodule. Wanneer deze wel iets teruggeeft, dan is het datatype hiervan steeds in de naam van de methode weergegeven. De eerste methode gaf een decimaal getal terug en werd daarom als ‘double’ gedeclareerd. De overige twee methodes gaven niets terug en werden daarom als ‘void’ (of leeg) gedeclareerd. 5.3.4 Rijen en lijsten Java laat het gebruik van rijen en lijsten toe. In deze thesis wordt niet met rijen of lijsten gewerkt. Er wordt echter wel met de klasse ArrayList gewerkt. Deze gegevensstructuur is in principe ook een rij, maar zijn lengte (aantal elementen dat het kan opslaan) moet niet op voorhand gedefinieerd zijn. De opgeslagen elementen moeten ook niet van hetzelfde type zijn. Zo kan in een ArrayList perfect karakters en gehele getallen samen worden opgeslagen. Het is echter wel mogelijk een bepaalde type te koppelen aan een ArrayList zodat enkel deze gegevens aanvaard worden. Voor met ArrayList te werken dient de package ‘java.util.*’ geïmporteerd te worden (analoog als bij java.io.*). Een ArrayList wordt als volgt gedefinieerd: ArrayList lijst = new ArrayList(); Een ArrayList van een bepaald type (bijvoorbeeld Double) is anders gedefinieerd: ArrayList
doublelijst = new ArrayList; Op deze lijsten kunnen uiteraard bewerkingen losgelaten worden zoals het toevoegen of verwijderen van gegevens of het simpelweg opvragen van een gegeven op een bepaalde positie in de lijst. In hoofdstuk 6 wordt dit toegepast. 5.3.5 External jars In deze thesis wordt er gewerkt met databanken en Excel-bestanden. Java heeft daar geen standaard packages voor en daarom dienen er gedownload te worden van het internet. Dit wordt een ‘external jar’ genoemd. Hieronder volgt een overzicht van de external jars die in dit project werden gebruikt. 5.3.5.1 Joda Time Door het toevoegen van ‘Joda Time’ wordt er in Java een uitgebreid arsenaal voorzien voor het werken met data en tijdstippen. 5.3.5.2 MySQL Connector ‘MySQL Connector’ zorgt ervoor dat er een verbinding mogelijk is tussen Java en de databanken.
99
5.3.5.3 POI Dankzij ‘POI’ kan er in Java gewerkt worden met gegevens afkomstig van Office-bestanden, zoals bijvoorbeeld Word en Excel. 5.3.5.4 Toevoegen van jars Voor de vereiste jars toe te voegen, dienen volgende stappen ondernomen te worden. Door met de rechtermuisknop op ‘src’ te klikken, kan naar ‘Configure Build Path’ gegaan worden.
Figuur 105: Build Path
Daarna verschijnt volgend scherm. Onder de tab ‘Libraries’ kan tenslotte met behulp van de knop ‘Add External Jars’ tenslotte de vereiste jars toegevoegd worden. Op onderstaande afbeelding staan alle jars die voor dit project gebruikt worden.
100
Figuur 106: Toevoegen van External Jars
Na deze stap gedaan te hebben, zijn de jars ter beschikking in Java, maar daarom nog niet geïmporteerd in het programma. Het importeren hiervan gebeurt volledig analoog als bij de standaard packages van Java Een voorbeeld hiervan is: import org.apache.poi.hssf.usermodel.HSSFWorkbook; 5.3.6 Thesis In wat voorafging zijn enkele bouwstenen van Java uitgelegd die nodig zijn voor deze thesis. In het volgende hoofdstuk worden de codes van deze thesis getoond en uitgelegd. Deze bouwstenen komen daar ook aan bod. Voor deze thesis werd met het programma Eclipse gewerkt. Dit programma maakt programmeren in Java mogelijk.
101
Hoofdstuk 6: Software In dit hoofdstuk worden de verschillende programma’s, die geprogrammeerd werden voor het doel van deze thesis te bereiken, uiteengezet. Alsook de eventuele problemen die hierbij voorkwamen, worden kort vermeld.
6.1
Programma om metergegevens naar de databank te sturen
In wat volgt, zal het programma stuk voor stuk uitgelegd worden. Het volledige programma en de programma’s die hierna volgen, kunnen op de bijgevoegde cd-rom teruggevonden worden. 6.1.1 Bibliotheken In onderstaande code worden de verschillende bibliotheken ingeladen. Hieronder wordt kort vermeld wat de functie is van elke bibliotheek. Wanneer een asterisk achter de naam staat (bijvoorbeeld “import java.io.*;”), wordt de volledige package ingeladen. Men kan dieper gaan door in plaats van de asterisk één iets specifieks te kiezen (bijvoorbeeld “import.java.io.File;”). Wanneer men echter de volledige package inlaadt, zal dit ene specifieke sowieso ook ingeladen worden.
Java.io: zorgt voor de systeem input en output doorheen datastromen, serialisatie en het bestandssysteem, wanneer men bijvoorbeeld wilt inlezen (met behulp van “in.readLine()”), zal ‘java.io.*’ hiervoor zorgen. Java.util: maakt onder andere het gebruik van ArrayList mogelijk. Java.sql: zorgt ervoor dat de data in een sql-databank toegankelijk wordt en verwerkt kan worden. Java.lang: voorziet klassen die fundamenteel zijn voor het design van de Java taal (bijvoorbeeld Boolean, Byte, …). Org.apache.poi: zorgt ervoor dat Java met Office-documenten (zoals in dit geval Excel) kan werken. Org.joda: zorgt ervoor dat men in Java een uitgebreider arsenaal heeft aan tijdsystemen (naast de standaard voorziene datum- en tijdsklassen).
Merk op dat deze laatste twee niet standaard in Java op te roepen zijn. Ze zijn pas beschikbaar na het toevoegen van external jars. De uitleg hiervan werd in hoofdstuk 5 al behandeld. // load the used libraries import java.io.*; import java.util.*; import java.sql.*; import java.lang.Object; import import import import import
org.apache.poi.hssf.usermodel.HSSFWorkbook; org.apache.poi.hssf.usermodel.HSSFCell; org.apache.poi.hssf.usermodel.HSSFRow; org.apache.poi.hssf.usermodel.HSSFSheet; org.apache.poi.ss.usermodel.Cell;
102
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.*; //import java.text.DateFormat; import java.util.Date; //import java.text.ParseException; //import java.text.*; import org.joda.time.format.*; import org.joda.time.DateTime;
6.1.2 Voorbereiding In het tweede stuk code zien we drie blokken:
De ‘InputStreamReader’ en ‘BufferedReader’, onderdeel van ‘java.io’, zorgen ervoor dat Java tekst kan inlezen die we zelf intypen wanneer het programma loopt. Dit wordt later nog eens geïllustreerd wanneer het programma gerund wordt. De ‘Connections’ worden gebruikt om connectie te maken met een databank en de ‘PreparedStatement’ om gegevens daarin te laden, eruit te halen, … Beiden zijn onderdeel van ‘java.sql’. De ArrayLists, mogelijk gemaakt dankzij ‘java.util’, zullen we verder nodig hebben om gegevens in op te slaan.
public class ReadMeteredEnergy7 { public static void main(String[] args) throws Exception { InputStreamReader isr = new InputStreamReader (System.in); BufferedReader in = new BufferedReader (isr); Connection con = null; Connection con00 = null; PreparedStatement pstmt00 = null; PreparedStatement pstmt0 = null; PreparedStatement pstmt = null; //ResultSet rs00 = null; //ResultSet rs0 = null; ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList
<Timestamp> Time = new ArrayList <Timestamp>(); <String> UTC = new ArrayList <String>(); consumption = new ArrayList (); <String> consumptionquality = new ArrayList <String>(); generation = new ArrayList (); <String> generationquality = new ArrayList <String>(); startlatitude = new ArrayList (); startlongitude = new ArrayList (); endlatitude = new ArrayList (); endlongitude = new ArrayList (); <String> positionsquality = new ArrayList <String>();
103
6.1.3 Selecteren van Excel-bestand In onderstaande code wordt het nut van ‘java.io’ duidelijk. Het programma vraagt eerst welke dag van de gemeten energie er naar de databank moet gestuurd worden. Dit is in de vorm ‘dd.mm.yyyy’, waar ‘d’ staat voor dag, ‘m’ voor maand en ‘y’ voor jaar. De gebruiker kan dit nu invullen (bv. 25.09.2013). De daaropvolgende dag dient ook ingevuld te worden (in dit geval dus 26.09.2013). Tot slot wordt de gewenste “klant” gevraagd (bijvoorbeeld SNCB Logistics). Deze gegevens werden telkens ingelezen met behulp van ‘in.readLine()’. De gewenste dag wordt opgeslagen in de String dmy, de daaropvolgende dag in de String dmy1 en de klant in de String customer. Met deze gegevens kan het pad ingevuld worden waar het bijhorende Excel-bestand staat. In de afbeelding na de code wordt het pad van dit voorbeeld weergegeven. Tot slot wordt nog een ‘workbook’ van dit Excel-bestand aangemaakt. Hiermee wordt later in de code meer mee gedaan. // read from Excel and create database try { // say which file should be used System.out.println("Which day (metered energy) should be sent to the database?"); System.out.println("Please enter in the form dd.mm.yyyy:"); String dmy = in.readLine(); System.out.println("Enter day +1 in the form dd.mm.yyyy:"); String dmy1 = in.readLine(); System.out.println("Which customer? You can choose between: Belgorail, Bouvet, Captrain Belgium, Crossrail, DBSNL, ERESS admin, EUROPORTE, Eurostar, Infrabel, NMBS, RAILTRAXX, SNCB Logistics and SNCF Fret"); String customer = in.readLine(); FileInputStream file = new FileInputStream(new File("C:\\Users\\Jil\\Desktop\\Thesis\\Java\\Excel-bestanden\\Energy 5 Minute Values ["+customer+"]["+dmy+" - "+dmy1+"].xls")); // create workbook instance holding reference to .xls file HSSFWorkbook workbook = new HSSFWorkbook(file);
Figuur 107: Pad naar Excel-bestand van energiemetergegevens
104
6.1.4 Connectie met MySQL en aanmaken van databank In de code hieronder wordt eerst de ‘driver’ geladen die voor de verbinding zorgt met MySQL Workbench. Hierbij worden de gebruikersnaam (root) en het wachtwoord (Infrabel4) meegegeven om de verbinding tot stand te brengen. Zorg er ook voor dat de server van MySQL lopende is (dit werd in hoofdstuk 5 getoond). // load driver, create schema and connect with username("root") and password("Infrabel4") Class.forName("com.mysql.jdbc.Driver"); con00 = DriverManager.getConnection("jdbc:mysql://localhost:3306", "root", "Infrabel4");
In de code daarop volgend, wordt een databank aangemaakt met als naam de tekst opgeslagen in de String dmy (hier is dit dus 25.09.2013). Dit wordt gedaan met behulp van PreparedStatements. Eens de databank aangemaakt is, kan een connectie (con) daarmee gelegd worden. String sql00 = "CREATE SCHEMA `" +dmy+ "`"; pstmt00 = con00.prepareStatement(sql00); pstmt00.executeUpdate(); con = DriverManager.getConnection("jdbc:mysql://localhost:3306/"+dmy, "root", "Infrabel4");
6.1.5 Aanmaken van tabellen binnen de databank Het Excel-bestand van de gegevens van de energiemeters bestaat uit verschillende bladen. Het eerste blad omvat een overzicht, de rest van de bladen zijn de gegevens per meter. Het is deze laatste categorie die we nodig hebben. De verschillende bladen worden nog eens weergegeven in onderstaande afbeelding.
Figuur 108: Verschillende bladen van het Excel-bestand met de energiemetergegevens
Elke meter heeft dus zijn eigen blad. De naam van deze meter wordt nog eens herhaald in kolom nul en rij nul (A1) van dat blad. Deze naam zal gebruikt worden om per meter een tabel te maken binnen de databank. Op onderstaande afbeelding wordt de naam van een bepaalde meter weergegeven.
105
Figuur 109: De naam van de meter op positie A1 (kolom nul en rij nul)
In onderstaande code zien we dat eerst het aantal bladen, aanwezig in de Excel-file, genomen wordt (int sheets). Dit aantal wordt dan in een for-lus doorlopen. De naam wordt uit A1 (rij nul en kolom nul) gehaald en vervolgens wordt het sql-commando doorgegeven dat de overeenkomstige tabel maakt. Bij elke iteratie van de for-lus wordt dus een tabel met kolommen (idMeter, Time, UTC+-, …) aangemaakt binnenin de databank voor een bepaalde meter. De kolomnamen van de databanktabel komen overeen met die van het Excel-bestand. int sheets = workbook.getNumberOfSheets(); //int sheets = 4; for (int iname = 1; iname<sheets; iname++) { HSSFSheet Sname = workbook.getSheetAt(iname); HSSFRow Rname = Sname.getRow(0); HSSFCell Cname = Rname.getCell(0); // create one table per meter and name it String sql0 = "CREATE TABLE `"+ dmy +"`.`"+ customer + "--" + Cname +"` (`idMeter` INT NOT NULL AUTO_INCREMENT,`Time` TIMESTAMP NULL,`UTC+-` VARCHAR(45) NULL,`consumption` DOUBLE NULL,`consumption quality` VARCHAR(45) NULL,`generation` DOUBLE NULL,`generation quality` VARCHAR(45) NULL,`start latitude` DOUBLE NULL,`start longitude` DOUBLE NULL,`end latitude` DOUBLE NULL,`end longitude` DOUBLE NULL,`positions quality` VARCHAR(45) NULL,PRIMARY KEY (`idMeter`))"; pstmt0 = con.prepareStatement(sql0); pstmt0.executeUpdate();
6.1.6 Invullen van kolommen binnen de databanktabel Nu dat de tabellen en kolommen aangemaakt zijn, kunnen deze laatste ingevuld worden. Daarvoor wordt een tussenstap ingevoerd. De waarden in het Excel-bestand worden eerst in een ArrayList opgeslagen (elke ArrayList wordt dus gevuld met de waarden van een corresponderende Excel-kolom). Iedere kolom in de databank die dient gevuld te worden, komt overeen met een ArrayList in Java. In het Excel-bestand wordt dus eerst iedere kolom om beurt doorlopen, vandaar het gebruik van twee for-lussen in onderstaande code (een voor elke kolom en een voor elke rij binnen die kolom). Nadat de kolommen doorlopen zijn, zijn de ArrayLists dus gevuld. Afhankelijk van de kolom waarmee gewerkt wordt in de databank, wordt de overeenkomstige ArrayList gekozen (de kolom Time in de databank komt zo overeen met de ArrayList Time). Hierbij wordt steeds rekening gehouden met het soort type van data (bijvoorbeeld VARCHAR in de databank komt overeen met String in Java, …). 106
In onderstaande code worden de ArrayLists gevuld. // get desired sheet from the workbook HSSFSheet sheet = workbook.getSheetAt(iname); int columns = 11; int rows = sheet.getLastRowNum(); for (int j = 0; j total milliseconds in a day //25569 --> days between 1 jan 1900 and 1 jan 1970 //7200000 --> correction of 2 hours long long1 = (long) double2; Timestamp d = new Timestamp(long1); Time.add(d); } else if (j==1) { UTC.add(cell.toString()); } else if (j==2) { consumption.add(cell.getNumericCellValue()); } else if (j==3) { consumptionquality.add(cell.toString()); } else if (j==4) { generation.add(cell.getNumericCellValue()); } else if (j==5) { generationquality.add(cell.toString()); } else if (j==6) { startlatitude.add(cell.getNumericCellValue()); } else if (j==7) { startlongitude.add(cell.getNumericCellValue()); } else if (j==8) {
107
endlatitude.add(cell.getNumericCellValue()); } else if (j==9) { endlongitude.add(cell.getNumericCellValue()); } else if (j==10) { positionsquality.add(cell.toString()); } } }
Het invullen van de ArrayLists van het type String en Double gebeurt zonder tussenstappen. Om echter een ArrayList van het type Timestamp in te vullen, dient eerst nog wat rekenwerk uitgevoerd te worden. Excel slaat zijn data en tijden op als kommagetallen. Het getal voor de komma is het aantal dagen die gepasseerd zijn sinds 0 januari 1900 (1 januari 1900 is dus 1). Het getal na de komma staat voor de fractionele portie van een volledige dag (24 uur). Zes uur in de ochtend is dan bijvoorbeeld 0,25. Brengen we deze twee componenten samen dan krijgen we voor bijvoorbeeld 19 januari 2000 3PM: 36544,625. Java begint zijn telling echter vanaf 1970 in plaats van 1900 (zoals Excel). Er dient ook rekening gehouden te worden met het feit dat België UTC +2 uur is in de zomertijd en UTC +1 uur in de wintertijd. Daarom zijn er twee programma’s: een voor de winter met een correctie van een uur (3600000 milliseconden) en een voor de zomer met een correctie van twee uur (7200000 milliseconden). 25 september 2013 valt volgens onderstaande tabel nog binnen de zomertijd en er wordt dus met een correctie van twee uur gewerkt. Tabel 1: Zomer- en wintertijd in 2013
Zomer- en wintertijd in 2013 Wintertijd Zomertijd Wintertijd
Startdatum
Einddatum
28.10.2012 31.03.2013 27.10.2013
30.03.2013 26.10.2013 29.03.2014
Aan de hand van bovenstaande gegevens kan de formule opgesteld worden voor de juiste datum en tijd. Deze formule kan ook in de bovenstaande code terug gevonden worden. Databank-datum = (Excel-datum - 25569)*86400000 – 7200000 (zomer) Databank-datum = (Excel-datum - 25569)*86400000 – 3600000 (winter) Hierbij is:
25569: 86400000:
aantal dagen tussen 1970 (Java) en 1900 (Excel) aantal milliseconden in een dag (24 x 60 x 60 x 1000) 108
7200000: 3600000:
correctie van 2 uur (in milliseconden) in de zomer (2 x 60 x 60 x 1000) correctie van 1 uur (in milliseconden) in de winter (1 x 60 x 60 x 1000)
In onderstaande code worden de databanktabellen gevuld met de waarden uit de ArrayLists. // fill the table with the data from the Excel file String sql = "INSERT INTO `"+ dmy +"`.`"+ customer + "--" + Cname+"` (`Time`, `UTC+-`, `consumption`, `consumption quality`, `generation`, `generation quality`, `start latitude`, `start longitude`, `end latitude`, `end longitude`, `positions quality`) VALUES (?,?,?,?,?,?,?,?,?,?,?)"; pstmt = con.prepareStatement(sql); int length = Time.size(); for (int q = 0; q
6.1.7 Ledigen van ArrayLists en afsluiten In onderstaande code worden de ArrayLists gewist zodat ze leeg zijn voor het volgende gebruik. Tenslotte worden de Excel-file, de verbinding met de databank en de PreparedStatements gesloten. Wanneer het programma met dit alles klaar is, zal er ‘Done’ verschijnen. //clean ArrayLists for new sheet in Excel file Time.clear(); UTC.clear(); consumption.clear(); consumptionquality.clear(); generation.clear(); generationquality.clear(); startlatitude.clear(); startlongitude.clear(); endlatitude.clear(); endlongitude.clear(); positionsquality.clear(); } file.close(); }
109
catch (Exception e) { throw e; } finally { //if (rs0 != null) //{ // rs0.close(); //} //if (rs00 != null) //{ // rs00.close(); //} if (pstmt0 != null) { pstmt0.close(); } if (pstmt00 != null) { pstmt00.close(); } if (con != null) { con.close(); } if (con00 != null) { con00.close(); } if (pstmt != null) { pstmt.close(); } } System.out.println("Done"); } }
6.1.8 Lopen van het programma voor de energiemetergegevens Wanneer in Eclipse op ‘Run’ geduwd wordt, zal het programma volgende uitvoer geven.
Figuur 110: Lopen van het programma voor de gemeten energie
Er werd dus gekozen voor 25 september 2013 en SNCB Logistics (handmatige invoer). Na enige tijd verschijnt ‘Done’. Hierna kan naar de databank gekeken worden. In MySQL Workbench is de databank 25.09.2013 nog niet aanwezig. Hiervoor dient eerst op ‘refresh’ 110
geduwd te worden, waarna de databank verschijnt en de gegevens opgevraagd kunnen worden.
Figuur 111: De databank is nog niet verschenen
Figuur 112: Na refresh verschijnt de databank en zijn tabellen
111
Figuur 113: Gegevens van een energiemetertabel
6.2
Programma om TMS-data naar de databank te schrijven
Een tweede programma bestaat erin om de TMS-data, afkomstig van de detectiepunten die de treinen passeren, naar de databank te zenden. Hiervoor werd gebruik gemaakt van één csvbestand. Dit bestand was echter te groot voor werking met de gebruikte laptop en werd bijgevolg opgeslagen in meerdere kleinere xlsx-bestanden. De code wordt wederom stuk voor stuk uitgelegd en kan op de cd-rom in zijn totaliteit terug gevonden worden. 6.2.1 Bibliotheken en voorbereiding Het principe achter het invoegen van de bibliotheken en de voorbereiding (Connections, PreparedStatements en ArrayLists) is analoog als bij het programma voor het inlezen van de energiemetergegevens. Hier wordt echter met andere gegevens gewerkt en dus ook met andere ArrayLists. // load the used libraries import java.io.*; import java.util.*; import java.sql.*; import java.lang.Object; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFRow;
import java.util.Iterator; //import //import //import //import
org.apache.poi.hssf.usermodel.HSSFWorkbook; org.apache.poi.hssf.usermodel.HSSFCell; org.apache.poi.hssf.usermodel.HSSFRow; org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ss.usermodel.*;
112
//import java.text.DateFormat; import java.util.Date; //import java.text.ParseException; //import java.text.*; import org.joda.time.format.*; import org.joda.time.DateTime; public class ReadTMSdata_opgesplitstefiles2_ZOMER { public static void main(String[] args) throws Exception { InputStreamReader isr = new InputStreamReader (System.in); BufferedReader in = new BufferedReader (isr); Connection con = null; Connection con00 = null; PreparedStatement pstmt00 = null; PreparedStatement pstmt0 = null; PreparedStatement pstmt = null; //ResultSet rs00 = null; //ResultSet rs0 = null; ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList
<String> TRAIN_NUM = new ArrayList <String>(); <String> DAT_DEP = new ArrayList <String>(); <Timestamp> DEP_TIME = new ArrayList <Timestamp>(); <Timestamp> ARR_TIME = new ArrayList <Timestamp>(); <String> TRAFFIC_CATEGORY = new ArrayList <String>(); UIC_ID = new ArrayList (); <String> TRAIN_OPERATOR = new ArrayList <String>(); TRAIN_TYPE = new ArrayList (); PRIORITY = new ArrayList (); <String> COMMERCIAL_TYPE = new ArrayList <String>(); <String> VALID_FROM_DATE = new ArrayList <String>(); <String> VALID_TO_DATE = new ArrayList <String>(); <String> ACRONYM = new ArrayList <String>(); ORD_NO = new ArrayList (); WEIGHT = new ArrayList (); <Timestamp> DEP_TIME_SECTION = new ArrayList <Timestamp>(); <Timestamp> ARR_TIME_SECTION = new ArrayList <Timestamp>(); DEP_PT = new ArrayList (); <String> PTCAR_DEP = new ArrayList <String>(); ARR_PT = new ArrayList (); <String> PTCAR_ARR = new ArrayList <String>(); GPSLAT_DEPARTURE = new ArrayList (); GPSLONG_DEPARTURE = new ArrayList (); GPSLAT_ARRIVAL = new ArrayList (); GPSLONG_ARRIVAL = new ArrayList (); <String> EVN = new ArrayList <String>();
6.2.2 Selecteren van Excel-bestand Nu wordt naast de datum ook het gedeelte na de opsplitsing gekozen (bijvoorbeeld 201309251 of 201309257 wordt ingegeven, dit komt overeen met 25 september 2013 gedeelte 1 of 7). Op deze manier wordt het juiste Excel-bestand gekozen. 113
// read from Excel and connect to database try { // say which file should be used System.out.println("Which day (TMS) should be sent to the database?"); System.out.println("Please enter in the form yyyymmddpart (for example: 201309251):"); String dmy = in.readLine(); String dmy1 = dmy.substring(6,8)+"."+dmy.substring(4,6)+"."+dmy.substring(0,4); FileInputStream file = new FileInputStream(new File("C:\\Users\\Jil\\Desktop\\Thesis\\Java\\Excelbestanden\\Splitsen\\"+dmy+"_01.xlsx")); // create workbook instance holding reference to .xls/.xlsx file XSSFWorkbook workbook = new XSSFWorkbook(file);
6.2.3 Connectie met MySQL en aanmaken en invullen van de tabel Het aanmaken van de databank wordt hier overgeslagen, daar deze al gecreëerd werd in het programma voor het zenden van de energiemetergegevens. Het komt er nu dus enkel op aan de bestaande databank verder aan te vullen met de TMS-data. Allereerst wordt de driver geladen. Vervolgens wordt er gekeken met welk gedeelte er gewerkt wordt. Indien er sprake is van het eerste gedeelte, dan moet de tabel nog aangemaakt worden. Bij de volgende gedeeltes dient enkel de verbinding met deze tabel nog tot stand gebracht te worden. Onderstaande code illustreert dit: de if-lus behandelt het eerste gedeelte, de else-lus de overige gedeeltes. // load driver, create schema and connect with username("root") and password("Infrabel4") Class.forName("com.mysql.jdbc.Driver"); if(dmy.substring(8).equals("1")) { con = DriverManager.getConnection("jdbc:mysql://localhost:3306/"+dmy1, "root", "Infrabel4"); String sql0 = "CREATE TABLE `"+dmy1+"`.`"+"TMS--"+dmy.substring(0,8)+"` (`idTMS` INT NOT NULL AUTO_INCREMENT,`TRAIN_NUM` VARCHAR(45) NULL,`DAT_DEP` VARCHAR(45) NULL,`DEP_TIME` TIMESTAMP NULL,`ARR_TIME` TIMESTAMP NULL,`TRAFFIC_CATEGORY` VARCHAR(45) NULL,`UIC_ID` INT NULL,`TRAIN_OPERATOR` VARCHAR(45) NULL,`TRAIN_TYPE` INT NULL,`PRIORITY` INT NULL,`COMMERCIAL_TYPE` VARCHAR(45) NULL,`VALID_FROM_DATE` VARCHAR(45) NULL,`VALID_TO_DATE` VARCHAR(45) NULL, `ACRONYM` VARCHAR(45) NULL, `ORD_NO` INT NULL, `WEIGHT` INT NULL, `DEP_TIME_SECTION` TIMESTAMP NULL, `ARR_TIME_SECTION` TIMESTAMP NULL, `DEP_PT` INT NULL, `PTCAR_DEP` VARCHAR(45) NULL, `ARR_PT` INT NULL, `PTCAR_ARR` VARCHAR(45) NULL, `GPSLAT_DEPARTURE` DOUBLE NULL,`GPSLONG_DEPARTURE` DOUBLE NULL, `GPSLAT_ARRIVAL` DOUBLE NULL, `GPSLONG_ARRIVAL` DOUBLE NULL, `EVN` VARCHAR(45) NULL ,PRIMARY KEY (`idTMS`))"; pstmt0 = con.prepareStatement(sql0); pstmt0.executeUpdate(); } else { con = DriverManager.getConnection("jdbc:mysql://localhost:3306/"+dmy1, "root", "Infrabel4");
114
}
Eerst worden de gegevens van het eerste gedeelte naar de databank verzonden. Als de Excelgegevens van het eerste gedeelte naar de databank verzonden zijn, komen de andere gedeeltes in chronologische volgorde (2, 3, 4, …) aan beurt. De gegevens van deze gedeeltes worden om beurt in de reeds aangemaakte tabel toegevoegd achter de gegevens van de voorgaande gedeeltes. De gegevens van het derde gedeelte komen zo achter die van het eerste en tweede gedeelte, nadat de gegevens van het tweede gedeelte werden toegevoegd achter die van het eerste gedeelte. De tabel wordt zo verder aangevuld totdat alle Excel-gedeeltes behandeld zijn. De tussenstap met opslag in ArrayLists wordt hier opnieuw toegepast en wordt hieronder verder uitgelegd. Aangezien dit Excel-bestand bewerkt is, wordt bij ‘getLastRowNum()’ niet de laatste rij met gegevens gegeven. Excel houdt hier ook rekening met de lege rijen. Daarom werd een extra telmechanisme toegevoegd die telt hoeveel ingevulde rijen er zijn in de eerste kolom. In deze eerste kolom komen geen gaten voor en is dus perfect voor deze telling. Dit aantal wordt opgeslagen in de integer rows2. Met behulp van deze rows2 kunnen vervolgens de ArrayLists aangevuld worden. Aangezien het Excel-bestand hier en daar gaten vertoond, wat bij de energiemetergegevens niet het geval was, moet daar eveneens rekening mee gehouden worden. Daarom wordt steeds nagegaan of er sprake is van een null-waarde of een ingevulde waarde. In het eerste geval wordt null aan de ArrayList toegevoegd (else-lus). In het tweede geval wordt de desbetreffende ingevulde waarde toegevoegd (if-lus). De omzetting naar Timestamp gebeurt volledig analoog als bij de energiemetergegevens. In onderstaande code wordt weergegeven hoe de ArrayLists aangevuld worden. XSSFSheet Sname = workbook.getSheetAt(0); int columns = 27; //27!!!!!!!!!!!!!!!!!!! int rows = Sname.getLastRowNum(); //if the excel file is edited, it also takes the empty rows in account System.out.println("LastRowNum(): "+String.valueOf(rows)); int rows2 =0; System.out.println("Give last row number: (10000 or variable in case of last part) "); String end = in.readLine(); int endd = Integer.parseInt(end); for (int kk = 1; kk<=endd; kk++) //count rows without empty ones { XSSFRow row = Sname.getRow(kk); XSSFCell cell = row.getCell(1); if(cell != null) { rows2++; }
115
} System.out.println("rows2: "+String.valueOf(rows2)); for (int j = 1; j
116
long long2 = (long) double4; Timestamp dd = new Timestamp(long2); ARR_TIME.add(dd); } else { ARR_TIME.add(null); } } else if (j==5) { if (cell != null) { TRAFFIC_CATEGORY.add(cell.toString()); } else { TRAFFIC_CATEGORY.add(null); } } else if (j==6) { if (cell != null) { int int2 = (int) cell.getNumericCellValue(); UIC_ID.add(int2); } else { UIC_ID.add(null); } } else if (j==7) { if (cell != null) { TRAIN_OPERATOR.add(cell.toString()); } else { TRAIN_OPERATOR.add(null); } } else if (j==8) { if (cell != null) { int int3 = (int) cell.getNumericCellValue(); TRAIN_TYPE.add(int3); } else { TRAIN_TYPE.add(null); } } else if (j==9) { if (cell != null)
117
{ int int4 = (int) cell.getNumericCellValue(); PRIORITY.add(int4); } else { PRIORITY.add(null); } } else if (j==10) { if (cell != null) { COMMERCIAL_TYPE.add(cell.toString()); } else { COMMERCIAL_TYPE.add(null); } } else if (j==11) { if (cell != null) { //VALID_FROM_DATE.add(cell.getDateCellValue()); VALID_FROM_DATE.add(cell.toString()); } else { VALID_FROM_DATE.add(null); } } else if (j==12) { if (cell != null) { //VALID_TO_DATE.add(cell.getDateCellValue()); VALID_TO_DATE.add(cell.toString()); } else { VALID_TO_DATE.add(null); } } else if (j==13) { if (cell != null) { ACRONYM.add(cell.toString()); } else { ACRONYM.add(null); } } else if (j==14) { if (cell != null) {
118
int int5 = (int) cell.getNumericCellValue(); ORD_NO.add(int5); } else { ORD_NO.add(null); } } else if (j==15) { if (cell != null) { int int6 = (int) cell.getNumericCellValue(); WEIGHT.add(int6); } else { WEIGHT.add(null); } } else if (j==16) { if (cell != null) { double double5 = cell.getNumericCellValue(); double double6 = (double5 - 25569)*86400000 - 7200000; //Excel starts counting from 1900, Java from 1970 long long3 = (long) double6; Timestamp ddd = new Timestamp(long3); DEP_TIME_SECTION.add(ddd); } else { DEP_TIME_SECTION.add(null); } } else if (j==17) { if (cell != null) { double double7 = cell.getNumericCellValue(); double double8 = (double7 - 25569)*86400000 - 7200000; //Excel starts counting from 1900, Java from 1970 long long4 = (long) double8; Timestamp dddd = new Timestamp(long4); ARR_TIME_SECTION.add(dddd); } else { ARR_TIME_SECTION.add(null); } } else if (j==18) { if (cell != null) { int int7 = (int) cell.getNumericCellValue();
119
DEP_PT.add(int7); } else { DEP_PT.add(null); } } else if (j==19) { if (cell != null) { PTCAR_DEP.add(cell.toString()); } else { PTCAR_DEP.add(null); } } else if (j==20) { if (cell != null) { int int8 = (int) cell.getNumericCellValue(); ARR_PT.add(int8); } else { ARR_PT.add(null); } } else if (j==21) { if (cell != null) { PTCAR_ARR.add(cell.toString()); } else { PTCAR_ARR.add(null); } } else if (j==22) { if (cell != null) { GPSLAT_DEPARTURE.add(cell.getNumericCellValue()); } else { GPSLAT_DEPARTURE.add(null); } } else if (j==23) { if (cell != null) { GPSLONG_DEPARTURE.add(cell.getNumericCellValue()); } else
120
{ GPSLONG_DEPARTURE.add(null); } } else if (j==24) { if (cell != null) { GPSLAT_ARRIVAL.add(cell.getNumericCellValue()); } else { GPSLAT_ARRIVAL.add(null); } } else if (j==25) { if (cell != null) { GPSLONG_ARRIVAL.add(cell.getNumericCellValue()); } else { GPSLONG_ARRIVAL.add(null); } } else if (j==26) { if (cell != null) { EVN.add(cell.toString()); } else { EVN.add(null); } } } }
Nadat de tussenstap met de ArrayLists voltooid is, kunnen deze gegevens aangevuld worden in de TMS-tabel van de databank. Ook hier wordt eerst gekeken of er sprake is van een nullwaarde of niet. Afhankelijk hiervan wordt gewerkt met een if-lus (ingevulde waarde) of een else-lus (null-waarde). Onderstaande code geeft dit weer, waarbij steeds rekening werd gehouden met het juiste type van de ArrayList en de databankkolom (String en VARCHAR, Timestamp en TIMESTAMP, Int en Integer, …). // fill the table with the data from the Excel file String sql = "INSERT INTO `"+dmy1+"`.`"+"TMS--"+dmy.substring(0,8)+"` (`TRAIN_NUM`, `DAT_DEP`, `DEP_TIME`, `ARR_TIME`, `TRAFFIC_CATEGORY`, `UIC_ID`, `TRAIN_OPERATOR`, `TRAIN_TYPE`, `PRIORITY`, `COMMERCIAL_TYPE`, `VALID_FROM_DATE`,`VALID_TO_DATE`,`ACRONYM`,`ORD_NO`,`WEIGHT`,`DEP_TIME_SECTION`,` ARR_TIME_SECTION`,`DEP_PT`,`PTCAR_DEP`,`ARR_PT`,`PTCAR_ARR`,`GPSLAT_DEPARTURE`,`GP SLONG_DEPARTURE`,`GPSLAT_ARRIVAL`,`GPSLONG_ARRIVAL`,`EVN`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; pstmt = con.prepareStatement(sql);
121
int length = TRAIN_NUM.size(); for (int q = 0; q
122
if(TRAIN_TYPE.get(q) != null) { pstmt.setInt(8, TRAIN_TYPE.get(q)); } else { pstmt.setNull(8, Types.INTEGER); } if(PRIORITY.get(q) != null) { pstmt.setInt(9, PRIORITY.get(q)); } else { pstmt.setNull(9, Types.INTEGER); } if(COMMERCIAL_TYPE.get(q) != null) { pstmt.setString(10, COMMERCIAL_TYPE.get(q)); } else { pstmt.setNull(10, Types.VARCHAR); } if(VALID_FROM_DATE.get(q) != null) { pstmt.setString(11, VALID_FROM_DATE.get(q)); } else { pstmt.setNull(11, Types.VARCHAR); } if(VALID_TO_DATE.get(q) != null) { pstmt.setString(12, VALID_TO_DATE.get(q)); } else { pstmt.setNull(12, Types.VARCHAR); } if(ACRONYM.get(q) != null) { pstmt.setString(13, ACRONYM.get(q)); } else { pstmt.setNull(13, Types.VARCHAR); } if(ORD_NO.get(q) != null) { pstmt.setInt(14, ORD_NO.get(q)); } else { pstmt.setNull(14, Types.INTEGER); } if(WEIGHT.get(q) != null) { pstmt.setInt(15, WEIGHT.get(q));
123
} else { pstmt.setNull(15, Types.INTEGER); } if(DEP_TIME_SECTION.get(q) != null) { pstmt.setTimestamp(16, DEP_TIME_SECTION.get(q)); } else { pstmt.setNull(16, Types.TIMESTAMP); } if(ARR_TIME_SECTION.get(q) != null) { pstmt.setTimestamp(17, ARR_TIME_SECTION.get(q)); } else { pstmt.setNull(17, Types.TIMESTAMP); } if(DEP_PT.get(q) != null) { pstmt.setInt(18, DEP_PT.get(q)); } else { pstmt.setNull(18, Types.INTEGER); } if(PTCAR_DEP.get(q) != null) { pstmt.setString(19, PTCAR_DEP.get(q)); } else { pstmt.setNull(19, Types.VARCHAR); } if(ARR_PT.get(q) != null) { pstmt.setInt(20, ARR_PT.get(q)); } else { pstmt.setNull(20, Types.INTEGER); } if(PTCAR_ARR.get(q) != null) { pstmt.setString(21, PTCAR_ARR.get(q)); } else { pstmt.setNull(21, Types.VARCHAR); } if(GPSLAT_DEPARTURE.get(q) != null) { pstmt.setDouble(22, GPSLAT_DEPARTURE.get(q)); } else {
124
pstmt.setNull(22, Types.DOUBLE); } if(GPSLONG_DEPARTURE.get(q) != null) { pstmt.setDouble(23, GPSLONG_DEPARTURE.get(q)); } else { pstmt.setNull(23, Types.DOUBLE); } if(GPSLAT_ARRIVAL.get(q) != null) { pstmt.setDouble(24, GPSLAT_ARRIVAL.get(q)); } else { pstmt.setNull(24, Types.DOUBLE); } if(GPSLONG_ARRIVAL.get(q) != null) { pstmt.setDouble(25, GPSLONG_ARRIVAL.get(q)); } else { pstmt.setNull(25, Types.DOUBLE); } if(EVN.get(q) != null) { pstmt.setString(26, EVN.get(q)); } else { pstmt.setNull(26, Types.VARCHAR); } pstmt.executeUpdate(); }
6.2.4 Ledigen van ArrayLists en afsluiten Tenslotte worden de gebruikte ArrayLists geledigd zodat ze vrij zijn voor het gebruik bij het volgende gedeelte. Het principe achter het afsluiten van het programma is dezelfde als bij het programma voor de energiemetergegevens. In onderstaande code worden de ArrayLists leeg gemaakt. //clean ArrayLists TRAIN_NUM.clear(); DAT_DEP.clear(); DEP_TIME.clear(); ARR_TIME.clear(); TRAFFIC_CATEGORY.clear(); UIC_ID.clear(); TRAIN_OPERATOR.clear(); TRAIN_TYPE.clear();
125
PRIORITY.clear(); COMMERCIAL_TYPE.clear(); VALID_FROM_DATE.clear(); VALID_TO_DATE.clear(); ACRONYM.clear(); ORD_NO.clear(); WEIGHT.clear(); DEP_TIME_SECTION.clear(); ARR_TIME_SECTION.clear(); DEP_PT.clear(); PTCAR_DEP.clear(); ARR_PT.clear(); PTCAR_ARR.clear(); GPSLAT_DEPARTURE.clear(); GPSLONG_DEPARTURE.clear(); GPSLAT_ARRIVAL.clear(); GPSLONG_ARRIVAL.clear(); EVN.clear();
In onderstaande code wordt het programma afgesloten. file.close(); } catch (Exception e) { throw e; } finally { //if (rs0 != null) //{ // rs0.close(); //} //if (rs00 != null) //{ // rs00.close(); //} if (pstmt0 != null) { pstmt0.close(); } if (pstmt00 != null) { pstmt00.close(); } if (con != null) { con.close(); } if (con00 != null) { con00.close(); } if (pstmt != null) { pstmt.close(); } }
126
System.out.println("Done"); } }
6.2.5 Probleem van “heap space” Wanneer het programma voor het inlezen van de TMS-data voor de eerste keer gerund wordt, verschijnt onderstaande error.
Figuur 114: OutOfMemoryError: Java heap space
Deze ‘OutOfMemoryError’ houdt in dat Java over onvoldoende geheugen beschikt om het programma naar behoren te doen lopen. De oplossing bestaat er hier in om het geheugen dat Eclipse krijgt, te vergroten. Hiervoor dienen de ‘Run Configurations’ geopend te worden (rechtermuisklik op de naam van het programma > ‘Run As’ > ‘Run Configurations …’). Dit wordt in onderstaande afbeelding weergegeven.
127
Figuur 115: Activeren van de Run Configurations in Eclipse
Eenmaal het blad ‘Run Configurations’ geopend is, kan het geheugen aangepast worden door in de ‘Arguments’-tab bij ‘VM arguments’ de volgende waarden toe te voegen:
-Xms1024m -Xmx1024m
Hier staat ‘Xms’ voor het minimum geheugen en ‘Xmx’ voor het maximum geheugen. Beide zijn hier aan elkaar gelijk gesteld, namelijk 1024 megabytes. Tenslotte dient op ‘Apply’ geduwd te worden.
128
Figuur 116: Aanpassen van het geheugen in Run Configurations
6.2.6 Lopen van het programma voor de TMS-data In onderstaande afbeelding wordt de gebruikersinvoer van het lopende programma weergegeven. De invoer is hier anders dan bij het programma voor de energiemetergegevens. Eerst wordt ingegeven welke dag en gedeelte naar de databank moet verzonden worden (201309251). Dit moet steeds in chronologische volgorde gebeuren, startend vanaf 1. Vervolgens dient eveneens het laatste ingevulde rijnummer meegegeven te worden, dit om de looptijd van het programma te reduceren. Zoals wordt weergegeven is de LastRowNum() niet de laatste ingevulde rij maar een willekeurige lege rij. Nadat handmatig de laatste rij wordt ingegeven, wordt het aantal ingevulde rijen geteld (rows2). Het weergeven van de waardes van LastRowNum() en rows2 is hier in principe overbodig, maar wordt toch weergegeven als controle voor de gebruiker. In principe zullen alle gegevens correct naar de databank worden verzonden zolang het zelf ingegeven laatste rijnummer groter of gelijk is aan het werkelijke laatste rijnummer met ingevulde gegevens. Elk Excel-bestand bevat 10000 ingevulde rijen. De uitzonderingen hierop zijn het eerste en het laatste Excel-bestand, namelijk 9999 rijen voor het eerste gedeelte en het aantal rijen die overblijven na het opslitsen van het grote csvbestand voor het laatste gedeelte. Het laatste gedeelte bevat sowieso minder dan 10000 rijen.
129
Figuur 117: Lopen van het programma voor de TMS-data
Nadat het programma afgelopen is, zal na op ‘refresh’ te hebben geduwd de TMS-tabel binnen de databank verschijnen. De databank bevat nu zowel de energiemetergegevens als de TMS-data. Dit kan op onderstaande afbeelding gezien worden.
Figuur 118: na refresh verschijnt de TMS-tabel
De inhoud van de TMS-tabel kan op volgende afbeelding bekeken worden.
Figuur 119: de TMS-tabel in de databank
130
6.3
Hoofdprogramma: deel 1
Het hoofdprogramma werd ter vereenvoudiging in delen opgesplitst. Dit werd gedaan omdat het zo gemakkelijker is elk deel apart te testen los van elkaar. Om een geschikte koppeling te vinden tussen een niet toegewezen energiemeter en een mogelijke treinrit, wordt er een extra kolom in de tabel van deze energiemeter toegevoegd. In deze kolom zullen mogelijke treinritten waaraan de energiemeter gekoppeld kan worden, weergegeven worden. Een van deze treinritten zal de juiste zijn. Het eerste deel van het hoofdprogramma voegt deze kolom aan de energiemetertabel toe. Het gaat om een lege kolom (met NULL-waarden). Het invullen van mogelijke treinritten gebeurt in het tweede deel van het hoofdprogramma. Hieronder staat de code van het eerste deel van het hoofdprogramma met bijhorende uitleg neergeschreven. 6.3.1 Importeren van de bibliotheken In onderstaande code worden de bibliotheken, nodig voor het werken van dit programma, ingeladen (sql, io en util). De ‘Connection’ en de ‘PreparedStatement’ worden eveneens al gedeclareerd. Hiermee zal later een connectie met de databank kunnen gemaakt worden. De ‘InputStreamReader’ en ‘BufferedReader’ maken het invoeren van tekst via het klavier mogelijk. import java.sql.*; import java.io.*; import java.util.*; public class MainProgramPart1_1 { public static void main(String[] args) throws Exception { Connection con = null; PreparedStatement pstmt = null; try { InputStreamReader isr = new InputStreamReader (System.in); BufferedReader in = new BufferedReader (isr);
6.3.2 Meegeven van gegevens In onderstaande code wordt in een do-while-lus de meters opgegeven die niet konden worden toegewezen aan een treinrit. Wanneer ‘D’ wordt meegegeven, eindigt het opgeven van de energiemeters. Deze energiemeters worden in een ArrayList opgeslagen. De datum dient hierna eveneens ingegeven te worden. Met deze datum kan dan verbinding gemaakt worden met de juiste databank.
131
String input; ArrayList <String> inputs = new ArrayList <String>(); int a = 0; do { System.out.println("Enter not allocated meter (for example: e 28-2813 (9188718620511)) or done (D):"); input = in.readLine(); inputs.add(input); a++; } while(input.charAt(0) != 'D'); a--; inputs.remove(a); a--; System.out.println("Enter date (dd.mm.yyyy):"); String date = in.readLine();
6.3.3 Connectie met de databank en toevoegen van kolom In onderstaande code wordt er eerst een verbinding met de databank (vandaar de nood aan het invoeren van de datum) gemaakt. Hierna wordt per opgegeven meter (deze wordt uit de ArrayList gehaald) in zijn corresponderende tabel een kolom toegevoegd. De naam van deze kolom, namelijk ‘bothOK’, is gekozen omdat men in het tweede deel van het hoofdprogramma zal controleren op overeenkomende tijdstippen en posities en als beide in orde zijn (both OK) dan kan de treinrit mogelijks gekoppeld worden aan de energiemeter. Nadat de kolom toegevoegd is, kan de lijst met de energiemeters leeg gemaakt worden. Class.forName("com.mysql.jdbc.Driver"); con = DriverManager.getConnection("jdbc:mysql://localhost:3306/"+date, "root", "Infrabel4"); for(int i = 0; i<=a; i++) { System.out.println(inputs.get(i)); String sql0 = "ALTER TABLE `"+date+"`.`sncb logistics-"+inputs.get(i)+"` ADD COLUMN `bothOK` VARCHAR(20000) NULL AFTER `positions quality`"; pstmt = con.prepareStatement(sql0); pstmt.executeUpdate(); } inputs.clear(); }
132
6.3.4 Afsluiten van het programma In onderstaande code wordt het programma afgesloten. Het einde van het programma wordt naar de gebruiker toe aangekondigd met “Done.”. catch (Exception e) { throw e; } finally { if (con != null) { con.close(); } if (pstmt != null) { pstmt.close(); } } System.out.println("Done."); } }
6.3.5 Lopen van het hoofdprogramma: deel 1 Op onderstaande afbeelding wordt de tabel van een energiemeter weergegeven voor het lopen van het programma. Er is hier nog geen sprake van een extra kolom.
133
Figuur 120: Tabel van een energiemeter voor het lopen van het hoofdprogramma: deel 1
Op onderstaande afbeelding wordt het lopen van het programma weergegeven. Eerst worden de energiemeters ingevuld. Hierna volgt het eindcommando van het invullen hiervan (‘D’). Vervolgens wordt de datum opgegeven. Daarna geeft het programma de meters weer waarbij hij een kolom heeft toegevoegd. Tenslotte eindigt het programma en de gebruiker kan dit lezen (‘Done.’).
Figuur 121: Lopen van het hoofdprogramma: deel 1
Na het lopen van het programma kan terug de tabel van de desbetreffende energiemeters opgevraagd worden. Nu is de kolom ‘bothOK’ aanwezig. Dit is op onderstaande afbeelding waarneembaar.
134
Figuur 122: Tabel van een energiemeter na het lopen van het hoofdprogramma: deel 1
6.4
Hoofdprogramma: deel 2
In het tweede gedeelte van het hoofdprogramma worden naar mogelijke kandidaat-treinritten gezocht die aan de energiemeter kunnen gekoppeld worden. De vereisten hiervan zijn het overeenkomen van de tijdstippen en de locaties. Er wordt zo steeds gezocht naar twee detectiepunten waartussen een gegeven van de energiemeter zich kan bevinden, dit zowel op vlak van tijd als locatie. Bij de locaties van de detectiepunten wordt nog een speling toegevoegd, aangezien het kan voorkomen dat het traject van een energiemeter zich wel tussen twee detectiepunten bevindt, maar door het kromme verloop ervan niet gedetecteerd kan worden. Onderstaande figuur verduidelijkt dit. Indien het doorgezonden tijdstip van de energiemeter tussen de doorrijdtijdstippen van de detectiepunten ligt, is er al een koppeling op basis van tijd. De koppeling op basis van posities gebeurt met een instelbare speling. Onderstaande figuur maakt duidelijk dat hoewel het traject van de energiemeter zich tussen twee detectiepunten bevindt, er zonder extra speling geen koppeling zal gevonden worden. Indien er gebruik gemaakt wordt van de speling is er echter wel een koppeling mogelijk.
135
Figuur 123: Detectiegebied met en zonder speling (herhaling)
Hieronder volgt de code met de uitleg van het tweede deel van het hoofdprogramma. 6.4.1 Importeren van de bibliotheken en aanmaken van ArrayLists In onderstaande code worden terug de nodige bibliotheken geïmporteerd. De ArrayLists nodig voor het opslaan van de gegevens van de detectiepunten (TMS-data) en de data van de energiemeters worden alsook gemaakt. De ‘static’ die hieraan toegevoegd is, maakt het gebruik van de ArrayLists in de methodes, dus buiten de hoofdmodule, mogelijk. import java.sql.*; import java.io.*; import java.util.*; public class TestingArrayMainProgramPart2_1 { //ArrayLists for static ArrayList static ArrayList static ArrayList static ArrayList static ArrayList static ArrayList static ArrayList static ArrayList
data from meters idMeter = new ArrayList (); <Timestamp> Time = new ArrayList <Timestamp>(); consumption = new ArrayList(); generation = new ArrayList(); startlatitude = new ArrayList(); startlongitude = new ArrayList(); endlatitude = new ArrayList(); endlongitude = new ArrayList();
//ArrayLists for TMS data static ArrayList idTMS = new ArrayList (); static ArrayList <String> TRAIN_NUM = new ArrayList <String>();
136
static static static static static static
ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList
<Timestamp> DEP_TIME_SECTION = new ArrayList <Timestamp>(); <Timestamp> ARR_TIME_SECTION = new ArrayList <Timestamp>(); GPSLAT_DEPARTURE = new ArrayList (); GPSLONG_DEPARTURE = new ArrayList (); GPSLAT_ARRIVAL = new ArrayList (); GPSLONG_ARRIVAL = new ArrayList ();
6.4.2 Declareren, ingeven en verbinden In onderstaande code wordt –analoog als bij de voorgaande programma’s- de nodige Connection, Statements, ResultSets en PreparedStatements gedeclareerd. Vervolgens worden terug de energiemeters opgegeven die geen koppeling met een treinrit hebben. De datum wordt ook ingevoerd en hier wordt in de code een variant van gemaakt: de datum in de tabelnaam van de TMS-data heeft namelijk een andere weergave dan de tabelnamen van de meters (bijvoorbeeld 20130925 in plaats van 25.09.2013). Tenslotte wordt een connectie met de databank gemaakt. public static void main(String[] args) throws Exception { long startTime = System.currentTimeMillis(); Connection con = null; PreparedStatement pstmt = null; PreparedStatement pstmt2 = null; ResultSet rs1 = null; ResultSet rs2 = null; ResultSet rs3 = null; ResultSet rs4 = null; ResultSet rs5 = null; ResultSet rs6 = null; Statement statement = null; Statement statement2 = null; try { InputStreamReader isr = new InputStreamReader (System.in); BufferedReader in = new BufferedReader (isr); String input; ArrayList <String> inputs = new ArrayList <String>(); int a = 0; do { System.out.println("Enter not allocated meter (for example: e 28-2813 (9188718620511)) or done (D), same as in part1:"); input = in.readLine(); inputs.add(input); a++; } while(input.charAt(0) != 'D'); a--; inputs.remove(a);
137
a--; System.out.println("Enter date (dd.mm.yyyy):"); String date = in.readLine(); String dd = date.substring(6)+date.substring(3,5)+date.substring(0,2); //System.out.println(dd); Class.forName("com.mysql.jdbc.Driver"); con = DriverManager.getConnection("jdbc:mysql://localhost:3306/"+date, "root", "Infrabel4"); statement = con.createStatement(); statement2 = con.createStatement();
6.4.3 Informatie naar de gebruiker toe In onderstaande code wordt een eerste for-lus doorlopen. Hierbij wordt aan de gebruiker getoond met welke meter het programma momenteel bezig is. Alsook het aantal elementen van deze meter en het aantal elementen van de TMS-tabel worden getoond. Dit laatste aantal zal per dag uiteraard een constant aantal zijn. Deze maxima worden met behulp van de databank in SQL berekend. Java stuurt een SQL-code naar de databank (via een Statement en een ResultSet die deze query uitvoert), waar de gegevens worden opgevraagd (hier is dit een maximum van de primaire sleutel of dus het aantal gegevens in de tabel waarin gewerkt wordt). Het opgevraagde wordt vervolgens via die ResultSet teruggegeven aan Eclipse (het Java-programma waarin geprogrammeerd werd) en via een opgeroepen methode (last) met als meegegeven parameter een ResultSet kan het maximum in Java worden opgeslagen. Het handige aan deze methode is dat ze slechts eenmaal geprogrammeerd moet worden, maar wel meerdere keren kan opgeroepen worden. Deze methode komt later nog aan bod. for(int j = 0; j<=a; j++) { String meter = inputs.get(j); System.out.println("----------------------------------------------"); System.out.println("Meter: "+ meter); System.out.println("----------------------------------------------"); String str = "SELECT max(idMeter) as maximum FROM `"+date+"`.`sncb logistics--"+meter+"`"; rs1 = statement.executeQuery(str); int maximum = last(rs1); System.out.println("meter maximum: " + maximum); String tms = "SELECT max(idTMS) as maximum FROM `"+date+"`.`tms--"+dd+"`"; rs3 = statement2.executeQuery(tms); int tmsmax = last(rs3); System.out.println("tms maximum: " + tmsmax);
138
6.4.4 Gegevens van de energiemeter in ArrayLists zetten In een tweede for-lus (genest in de eerste for-lus) worden de ArrayLists, voorzien voor de data van de energiemeters, gevuld. Hiervoor wordt eveneens een methode gebruikt (fill). Deze methode heeft als meegegeven parameter een ResultSet. Deze methode wordt later nog uitgelegd. for(int k = 1; k<= maximum; k++) { String str2 = "SELECT * FROM `"+date+"`.`sncb logistics--"+meter+"` WHERE idMeter = "+k; rs2 = statement.executeQuery(str2); fill(rs2); }
6.4.5 Detectiepuntgegevens in ArrayLists zetten Aangezien alle gegevens van de PTCAR’s onmogelijk in ArrayLists kunnen wegens geheugenproblemen van de laptop waarmee gewerkt wordt, dient er in stappen gewerkt te worden. Daarom wordt er per 10000 TMS-gegevens gewerkt. De gegevens van de energiemeter worden eerst vergeleken met deze eerste 10000 en eventuele mogelijke koppelingen worden in de extra kolom (bothOK) opgeslagen. Nadat deze cyclus voltooid is, wordt er naar de volgende 10000 gegaan. Dit blijft zich herhalen totdat alles vergeleken is met elkaar. Voor 25 september 2013 zullen er 14 cycli zijn (er zijn namelijk 130849 TMSgegevens). Het spreekt voor zich dat in de laatste cyclus per meterelement er geen 10000 maar 849 vergelijkingen zullen plaatsvinden voor die dag. Het begin en einde van elke cyclus wordt in de if-else-structuur berekend. Hierbij behandelt de if-structuur steeds de laatste cyclus en de else-structuur alle voorgaande cycli. Er wordt ook aan de gebruiker getoond aan welke cyclus (ten opzichte van het totale aantal cycli) het programma bezig is. De for-lus in onderstaande code (genest in de eerste for-lus) doorloopt elke cyclus. In deze for-lus wordt met behulp van de if-else-structuur, die daarnet werd uitgelegd, het begin en einde van elke cyclus berekend. Deze begin- en eindwaarde wordt vervolgens in een andere for-lus (genest in de for-lus die de cycli doorloopt) gebruikt om de ArrayLists met behulp van een methode (fill2) te vullen. double predivision = tmsmax; double divisionn = predivision/10000; int division = (int) Math.ceil(divisionn); //System.out.println(">>>>>>>>>>>>>>> " + division); for(int kk = 1; kk<= division; kk++) { System.out.println("Cyclus: "+kk+"/"+division); int iteration_start; int iteration_end; if(kk == division)
139
{ iteration_start = (kk - 1)*10000 + 1; iteration_end = tmsmax; } else { iteration_start = (kk - 1)*10000 + 1; iteration_end = kk * 10000; } for(int kkk = iteration_start; kkk <= iteration_end; kkk++) { String query = "SELECT * FROM `"+date+"`.`tms--"+dd+"` WHERE idTMS = "+kkk; rs6 = statement2.executeQuery(query); fill2(rs6); }
6.4.6 Vergelijken van de energiemeter met de TMS-data Nadat de ArrayLists, zowel voor de energiemeter waarmee op dat moment gewerkt wordt als voor de TMS-data, gevuld zijn, kan een vergelijking tussen beide gemaakt worden. Elk element van de energiemeter (eerste for-lus hieronder) wordt vergeleken met de 10000 (of een andere waarde in de laatste cyclus) gegevens van de detectiepunten (tweede for-lus hieronder). Nadat dit element van de energiemeter vergeleken is, wordt overgegaan naar het volgende element van de energiemeter. Voor de vergelijking wordt eveneens een methode gebruikt (between). Deze methode wordt later uitgelegd. Hieraan wordt onder andere de waarde die zich in de bothOK-kolom van het energiemeterelement (dat op dat moment vergeleken wordt) bevindt als paramater meegegeven. Deze parameter wordt dankzij een methode (bOK) bekomen. De werking hiervan wordt eveneens later uitgelegd. Bij een mogelijke koppeling geeft de methode ‘between’ een String terug. Deze String bevat een SQL-code waarmee de bothOK-kolom veranderd wordt. Op deze manier worden kandidaat-treinritten aan deze kolom toegevoegd. Indien er geen koppeling mogelijk was, wordt een lege String teruggegeven en gebeurt er verder niets. Wanneer er overgeschakeld wordt naar de volgende 10000 gegevens, dan worden de ArrayLists van de TMS-data geledigd en opnieuw gevuld met deze nieuwe 10000. Het ledigen van deze lijsten is hieronder eveneens in codevorm neergeschreven. for(int jj = 1; jj <= maximum; jj++) { for(int loop = 1; loop <= iteration_end (iteration_start - 1); loop++) { String sen2 = "SELECT bothOK FROM `"+date+"`.`sncb logistics--"+meter+"` WHERE idMeter = "+jj; rs5 = statement.executeQuery(sen2); String eee = bOK(rs5);
140
String update = between(date, meter, eee, jj, loop); if(update.equals("")) { } else { pstmt2 = con.prepareStatement(update); pstmt2.executeUpdate(); } } } idTMS.clear(); TRAIN_NUM.clear(); DEP_TIME_SECTION.clear(); ARR_TIME_SECTION.clear(); GPSLAT_DEPARTURE.clear(); GPSLONG_DEPARTURE.clear(); GPSLAT_ARRIVAL.clear(); GPSLONG_ARRIVAL.clear(); }
Nadat een energiemeter vergeleken is met alle gegevens van de detectiepunten, dan kan overgegaan worden naar de volgende meter. De lijsten van de meters worden geledigd en de volgende meter kan hier zijn intrede doen. Het ledigen van deze energiemeterlijsten wordt hieronder weergegeven. Het spreekt voor zich dat het opnieuw vullen van de lijsten – zowel voor de TMS-data als de gegevens van de meters – gebeurt in de stukken code die eerder al aan bod kwamen. Het gebruik van de for-lussen zorgt er namelijk voor dat de code steeds opnieuw wordt uitgevoerd totdat de eindvoorwaarde bereikt is. Time.clear(); startlatitude.clear(); startlongitude.clear(); endlatitude.clear(); endlongitude.clear(); idMeter.clear(); consumption.clear(); generation.clear(); }
6.4.7 Afsluiten van het programma Nadat alle vergelijkingen gebeurd zijn en dus de mogelijke koppelingen in de databank zijn toegevoegd, kan de lijst met de energiemeters leeg gemaakt worden. Vervolgens wordt het 141
programma afgesloten. Naast het aangeven van het einde van het programma (“Done.”), wordt eveneens het tijdsverloop van het programma weergegeven. In het begin van deze programmacode werd een tijdstip opgevraagd (zie eerste stuk code). Nu wordt wederom een tijdstip opgevraagd. Deze twee tijdstippen worden van elkaar afgetrokken en het resultaat hiervan wordt in milliseconden uitgedrukt. Na de nodige conversies wordt het tijdsverloop in uren en minuten getoond. Het is belangrijk dat dit tijdsverloop niet te hoog oploopt. Er werden meerdere programma’s geschreven en getest. Dit programma kwam uiteindelijk als overwinnaar uit de bus met een tijd van 2 u en 40 min voor de behandeling van 25 september 2013. De andere programma’s hadden meer dan 9 u nodig om tot hetzelfde resultaat te komen. inputs.clear(); } catch (Exception e) { throw e; } finally { if (con != null) { con.close(); } if (pstmt != null) { pstmt.close(); } if (pstmt2 != null) { pstmt2.close(); } if (rs1 != null) { rs1.close(); } if (rs2 != null) { rs2.close(); } if (rs3 != null) { rs3.close(); } if (rs4 != null) { rs4.close(); } if (rs5 != null) { rs5.close(); } if (rs6 != null) { rs6.close();
142
} if (statement != null) { statement.close(); } if (statement2 != null) { statement2.close(); } } long endTime = System.currentTimeMillis(); long totalTime = endTime - startTime; System.out.println("Running time of program: "+ Math.floor(totalTime/3600000)+"h "+ Math.floor(totalTime/60000 (Math.floor(totalTime/3600000)*60)) +"m "); System.out.println("Done."); }
6.4.8 Methode last Onderstaande code geeft de methode last weer. Er werd in de hoofdmodule een ResultSet meegegeven die als resultaat het maximum geeft. Dit maximum wordt er hier uitgehaald en opgeslagen in Java. Vervolgens wordt deze waarde (getal) aan de hoofdmodule gegeven. static int last(ResultSet rs1) throws SQLException { int getal = 0; while (rs1.next()) { getal = rs1.getInt("maximum"); } return getal; }
6.4.9 Methode fill In de hoofdmodule werd eveneens een ResultSet meegegeven. Deze ResultSet bevat één rij aan gegevens uit de tabel van een energiemeter. Deze gegevens worden vervolgens in de passende ArrayList opgeslagen. Bij het tijdstip wordt er vijf minuten bijgeteld eer het in de lijst wordt opgeslagen. Dit komt doordat de tijdstippen die in het Excel-bestand van de energiemeters staan, de begintijdstippen zijn van de vijf minuten-intervallen. Het opslaan van de gegevens gebeurt echter op het eindtijdstip, dus vijf minuten later. Vandaar worden deze vijf minuten in rekening gebracht. static void fill(ResultSet rs2) throws SQLException { while (rs2.next())
143
{ int id = rs2.getInt("idMeter"); Timestamp t = rs2.getTimestamp("Time"); t.setTime(t.getTime() + (5*60*1000)); double c = rs2.getDouble("consumption"); double g = rs2.getDouble("generation"); double slatitude = rs2.getDouble("start latitude"); double slongitude = rs2.getDouble("start longitude"); double elatitude = rs2.getDouble("end latitude"); double elongitude = rs2.getDouble("end longitude"); idMeter.add(id); Time.add(t); consumption.add(c); generation.add(g); startlatitude.add(slatitude); startlongitude.add(slongitude); endlatitude.add(elatitude); endlongitude.add(elongitude); //System.out.println(id + " - " + t + " - " + c + " - " + g + " - " + slatitude + " - " + slongitude + " - " + elatitude + " - " + elongitude); } }
6.4.10 Methode fill2 In deze methode gebeurt hetzelfde als in de voorgaande methode, maar dan voor de gegevens van de PTCAR’s in plaats van de energiemeters. De ArrayLists die gevuld worden, zijn uiteraard anders. static void fill2(ResultSet rs6) throws SQLException { while (rs6.next()) { int id = rs6.getInt("idTMS"); String TN = rs6.getString("TRAIN_NUM"); Timestamp DT_SECTION = rs6.getTimestamp("DEP_TIME_SECTION"); Timestamp AT_SECTION = rs6.getTimestamp("ARR_TIME_SECTION"); double LAT_DEPARTURE = rs6.getDouble("GPSLAT_DEPARTURE"); double LONG_DEPARTURE = rs6.getDouble("GPSLONG_DEPARTURE"); double LAT_ARRIVAL = rs6.getDouble("GPSLAT_ARRIVAL"); double LONG_ARRIVAL = rs6.getDouble("GPSLONG_ARRIVAL"); idTMS.add(id); TRAIN_NUM.add(TN); DEP_TIME_SECTION.add(DT_SECTION); ARR_TIME_SECTION.add(AT_SECTION); GPSLAT_DEPARTURE.add(LAT_DEPARTURE); GPSLONG_DEPARTURE.add(LONG_DEPARTURE); GPSLAT_ARRIVAL.add(LAT_ARRIVAL); GPSLONG_ARRIVAL.add(LONG_ARRIVAL); } }
144
6.4.11 Methode between Dit is het stuk code dat zich bezighoudt met het vinden van linken tussen de energiemeters en de detectiepunten. Deze methode krijgt allerlei parameters mee: de datum, de meter waarmee gewerkt wordt, de waarde in de kolom bothOK van het energiemeterelement dat op dat moment vergeleken wordt met de 10000 TMS-gegevens (of een ander aantal in de laatste cyclus), de positie van dit energiemeterelement in de ArrayLists en de positie van één van de 10000 (of ander aantal bij de laatste cyclus) gegevens in de ArrayLists. In de methode between wordt er dus een één op één vergelijking gedaan. Een gegeven van de energiemeter wordt vergeleken met één gegeven van de detectiepunten. Daarom wordt deze methode in de hoofdmodule in for-lussen altijd opnieuw opgeroepen om de vergelijkingen tussen alle elementen van de energiemeters en de TMS-data te verwezenlijken. Er wordt gekeken of het tijdstip van de energiemeter tussen het begin- en eindtijdstip van de twee detectiepunten ligt. Bij dit begin- en eindtijdstip wordt een extra 10s afgetrokken en bijgeteld. Indien dit niet wordt gedaan, dan zou bij een overlap van één van deze twee tijdstippen met het tijdstip van de energiemeter geen koppeling gemaakt kunnen worden. Bij de vergelijking van de posities wordt, zoals eerder al vermeld, een speling (range) toegevoegd. Het gaat hier om coördinaten met een breedte- en lengteligging. Het optellen van 0.00012 bij zo’n coördinaat komt overeen met een verplaatsing van ongeveer 13 meter. In onderstaande code werd gebruik gemaakt van een speling van 0.0011 (dus ongeveer 120 meter). Aangezien de trein vanuit alle richting kan komen (van boven naar onder of van onder naar boven in combinatie met van links naar rechts of van rechts naar links) wordt op vlak van breedte (latitude) en lengte (longitude) een dubbele controle (lat1 en lat2 voor de latitude, lon1 en lon2 voor de longitude) uitgevoerd. De trein kan op vlak van breedte namelijk in twee richtingen komen en op vlak van lengte eveneens in twee richtingen komen. Het echte traject is hier dan een combinatie van. Als beide gegevens (de energiemeter en de twee detectiepunten) overeenkomen, moet de bothOK-kolom aangevuld worden met de treinrit. Er wordt hier een String voor aangemaakt en teruggestuurd naar de hoofdmodule. Daar zal deze String (met het SQL commando) naar de databank verzonden worden. Zo wordt de bothOK-kolom steeds geüpdatet. Wanneer er aan de bothOK-kolom een waarde wordt toegevoegd dan mogen de eerdere kandidaat-treinritten uiteraard niet gewist worden. Daarom wordt de nieuwe treinrit bij de oude waarde toegevoegd. Elke treinrit kan in de kolom onderscheiden worden van de rest met behulp van een koppelteken (-). static String between(String date, String meter, String bOK, int position_meter, int loop) throws SQLException { String change = ""; position_meter--;
145
loop--; Timestamp DT_S = DEP_TIME_SECTION.get(loop); DT_S.setTime(DT_S.getTime() - 10000); Timestamp AT_S = ARR_TIME_SECTION.get(loop); AT_S.setTime(AT_S.getTime() + 10000); //10 s extra range (10 * 1000 milliseconds) double range = 0.0011; // 0.00012 is about 13 m, 0.005 is about 500 m boolean t = Time.get(position_meter).after(DT_S) && Time.get(position_meter).before(AT_S); boolean lat1 = (endlatitude.get(position_meter) >= (GPSLAT_DEPARTURE.get(loop) - range)) && (endlatitude.get(position_meter) <= (GPSLAT_ARRIVAL.get(loop) + range)); boolean lat2 = (endlatitude.get(position_meter) <= (GPSLAT_DEPARTURE.get(loop) + range)) && (endlatitude.get(position_meter) >= (GPSLAT_ARRIVAL.get(loop) - range)); boolean lon1 = (endlongitude.get(position_meter) >= (GPSLONG_DEPARTURE.get(loop) - range)) && (endlongitude.get(position_meter) <= (GPSLONG_ARRIVAL.get(loop) + range)); boolean lon2 = (endlongitude.get(position_meter) <= (GPSLONG_DEPARTURE.get(loop) + range)) && (endlongitude.get(position_meter) >= (GPSLONG_ARRIVAL.get(loop) - range)); if(t == true && (lat1 == true || lat2 == true) && (lon1 == true || lon2 == true)) { String TN; if(bOK.equals("")) { TN = TRAIN_NUM.get(loop); } else { TN = bOK + "-" + TRAIN_NUM.get(loop); } change = "UPDATE `"+date+"`.`sncb logistics--"+meter+"` SET `bothOK`='"+TN+"' WHERE `idMeter`='"+idMeter.get(position_meter)+"';"; } else { change = ""; } return change; }
6.4.12 Methode bOK Deze methode haalt de waarde uit de bothOK-kolom van het element waar op dat moment mee gewerkt wordt. Aangezien de bothOK-kolom na de between-methode steeds veranderd
146
wordt, moet deze bothOK-waarde bij het vergelijken steeds weer opnieuw opgevraagd worden. Het is daarom handig dit in een methode te schrijven. static String bOK(ResultSet rs4) throws SQLException { String bothOK = ""; while (rs4.next()) { if(rs4.getString("bothOK") == null) { bothOK = ""; } else { bothOK = rs4.getString("bothOK"); } } return bothOK; } }
6.4.13 Lopen van het hoofdprogramma: deel 2 Op onderstaande afbeeldingen wordt het uitgevoerde programma weergegeven. De eerste afbeelding toont het invoeren van de energiemeters en de datum. Daarna wordt weergegeven met welke meter en cyclus het programma bezig is (op onderstaande afbeelding is dit dus meter e 28-2832 (9188718622421) en cyclus 4). Per meter wordt ook het aantal gegevens weergegeven. Het aantal gegevens afkomstig van de detectiepunten staat ook aangeduid.
147
Figuur 124: Het lopen van het hoofdprogramma: deel 2
Het einde van het programma wordt aangekondigd zoals op onderstaande afbeelding. De tijd die het programma nodig had, wordt alsook getoond.
148
Figuur 125: Einde van het hoofdprogramma: deel 2
Nadat het programma zijn werk gedaan heeft, is de databank aangevuld met kandidaattreinritten die misschien aan de energiemeter kunnen gekoppeld worden. Een voorbeeld van hoe de databank er na het programma uitziet, wordt hieronder afgebeeld.
149
Figuur 126: De databank na het uitvoeren van het hoofdprogramma: deel 2
6.5
Hoofdprogramma: deel 3
In het tweede deel van het hoofdprogramma werd er gezocht naar kandidaat-treinritten die bij een bepaalde niet toegewezen energiemeter passen op vlak van tijdstippen en locaties. Bij elk meterelement werden zo één of meerdere kandidaten bekomen. Er werden zo veel treinritten gevonden. In het derde deel van het hoofdprogramma wordt er naar de deelverzameling hiervan gezocht die het best past bij de energiemeter. Er zal in dit programma bijgehouden worden hoe vaak een bepaalde treinrit voorkomt. De treinritten die het meest voorkomen, zijn dan ook de belangrijkste kandidaten. Op bovenstaande afbeelding valt op dat niet elk element van de energiemeter gekoppeld is aan een treinritnummer of meerdere treinritnummers; er staan namelijk ‘null’-waarden. Dit is niet erg, het kan namelijk voorkomen dat een trein er minder dan vijf minuten over doet om tussen twee detectiepunten te rijden. Aangezien de energiemeter om de vijf minuten zijn waarden berekent, kan het voorkomen dat de meter tussen deze twee detectiepunten geen berekeningen doet. Daarom worden er bij dat meterelement ook geen kandidaat-treinritten gevonden. Dit betekent daarom niet dat dit element niet tot die treinrit hoort. Zo valt op bovenstaande afbeelding duidelijk op dat de eerste null-waarde bij de treinrit ‘46255’ hoort. Zoals al eerder werd vermeld, zijn de treinritten die het vaakst voorkomen de belangrijkste kandidaten en enkel deze kandidaten dienen als nieuwe voorstellen terug naar Erex gestuurd te worden voor controle aan de hand van de validatieregels. Om te bepalen wanneer genoeg 150
eindkandidaten gevonden zijn, wordt een cumulatieve som van distinctieve aantallen bijgehouden. Op deze manier wordt van de belangrijkste treinritkandidaten distinctief opgeteld hoe vaak ze voorkomen, dit distinctief optellen houdt in dat wanneer een treinritnummer meerdere malen voorkomt bij hetzelfde meterelement dit slechts eenmaal geteld wordt. Dit betekent dus dat het totale aantal van voorkomen van een treinrit steeds groter of gelijk aan het distinctieve totale aantal zal zijn. Om het concept tussen deze twee begrippen te verduidelijken, wordt hieronder een tabel weergegeven die dit illustreert. In onderstaande voorbeeldtabel wordt dit enkel berekend voor kandidaat-treinrit ‘47890’, het spreekt voor zich dat dit in het programma voor alle kandidaten wordt berekend. Tabel 2: Voorbeeld van totale en distinctieve totale som
Meterelement 1 2 3 4 5 6
Kandidaten 1012 - 47890 47890 – 47890 47890 6789 -47890 47890 - 47890 1012
47890 (totaal) 1 3 4 5 7 7
47890 (distinctief totaal) 1 2 3 4 5 5
Dit wordt in het programma berekend voor alle treinritnummers en vervolgens in een lijst geordend van hoge naar lage totale aantal (niet distinctieve totale aantal). Er wordt via SQL gevraagd hoeveel meterelementen er zijn met voorgestelde treinritten (dus de elementen in de ‘bothOK’-kolom die niet ‘null’ zijn). Dit aantal wordt in Java opgeslagen. Vervolgens wordt in de geordende lijst op basis van het totale aantal, cumulatief het distinctieve totale aantal opgeteld. Wanneer dit cumulatieve aantal de waarde, die via sql werd opgevraagd, overschrijdt, zijn de belangrijkste kandidaten gevonden. Dit wordt in onderstaande tabel geïllustreerd. De belangrijkste kandidaten zijn aangegeven met een ‘x’. Tabel 3: Principe van het cumulatief distinctief aantal
Kandidaat Totaal
47890 44236 1089 6789 58932
20 15 10 5 2
Distinctief totaal 18 15 10 4 2
Cumulatief distinctief totaal 18 33 43 47 49
SQLwaarde
Belangrijke kandidaten
35 35 35 35 35
x x
Hieronder volgt de code met uitleg die de principes, die hierboven werden uitgelegd, hanteert.
151
6.5.1 Importeren van de bibliotheken en aanmaken van ArrayLists In onderstaande code worden de nodige bibliotheken ingeladen. De vereiste ArrayLists voor het programma worden eveneens aangemaakt. Er wordt hier een ArrayList voorzien voor de waarden op te slaan die zich in de ‘bothOK’-kolom van de tabel van de desbetreffende meter bevinden. Er worden eveneens drie ArrayLists gemaakt die treinritnummers bevatten, met hun corresponderend aantal en distinctieve aantal en vervolgens drie andere ArrayLists die dezelfde gegevens bevatten, maar dan geordend van de treinrit met het grootste aantal naar de treinrit met het laagste aantal. De lijsten ‘train_nrs’, ‘amount’ en ‘amount_distinct’ hebben een relatie met elkaar. Namelijk het treinritnummer dat zich op de eerste positie in ‘train_nrs’ bevindt heeft een totaal aantal en een distinctief totaal aantal. Deze kunnen respectievelijk teruggevonden worden op de eerste positie van de lijsten ‘amount’ en ‘amount_distinct’. Dit betekent dus dat de drie waarden in deze drie lijsten op dezelfde positie in de lijsten bij elkaar horen. Bij de geordende (“ordered”) lijsten is dit ook zo. Deze lijsten bevatten dezelfde gegevens maar dan geordend volgens het totale aantal. import java.sql.*; import java.io.*; import java.util.*; public class MainProgramPart3_1 { static static static static static static static static ();
ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList ArrayList
<String> bothOK = new ArrayList <String>(); <String> train_nrs = new ArrayList <String>(); amount = new ArrayList (); amount_distinct = new ArrayList (); <String> temporary = new ArrayList <String>(); <String> ordered_train_nrs = new ArrayList <String>(); ordered_amount = new ArrayList (); ordered_amount_distinct = new ArrayList
6.5.2 Declareren, ingeven en verbinden In onderstaande code worden terug de vereiste gegevens gedeclareerd (Connection, PreparedStatements, ResultSets en Statement). De energiemeters waarmee gewerkt worden (dit zijn dezelfde als bij deel 1 en deel 2 van het hoofdprogramma), worden eveneens ingegeven en opgeslagen in een lijst. Tenslotte wordt een verbinding gemaakt met de databank aan de hand van de opgegeven datum. public static void main(String[] args) throws Exception { Connection con = null; PreparedStatement pstmt = null; PreparedStatement pstmt2 = null; ResultSet rs1 = null; ResultSet rs2 = null;
152
ResultSet rs3 = null; ResultSet rs4 = null; Statement statement = null; try { InputStreamReader isr = new InputStreamReader (System.in); BufferedReader in = new BufferedReader (isr); String input; ArrayList <String> inputs = new ArrayList <String>(); int a = 0; do { System.out.println("Enter not allocated meter (for example: e 28-2813 (9188718620511)) or done (D):"); input = in.readLine(); inputs.add(input); a++; } while(input.charAt(0) != 'D'); a--; inputs.remove(a); a--; System.out.println("Enter date (dd.mm.yyyy):"); String date = in.readLine(); Class.forName("com.mysql.jdbc.Driver"); con = DriverManager.getConnection("jdbc:mysql://localhost:3306/"+date, "root", "Infrabel4"); statement = con.createStatement();
6.5.3 Aanmaken van de kolom ‘propose’ in de tabel van de meter In onderstaande code wordt een extra kolom in de tabel van elke ingegeven meter toegevoegd. Deze kolom ‘propose’ zal enkel de belangrijkste treinritten van de ‘bothOK’-kolom bevatten na uitvoer van dit programma. for(int ii = 0; ii<=a; ii++) { //System.out.println(inputs.get(i)); String sql0 = "ALTER TABLE `"+date+"`.`sncb logistics-"+inputs.get(ii)+"` ADD COLUMN `propose` VARCHAR(200) NULL AFTER `bothOK`"; pstmt = con.prepareStatement(sql0); pstmt.executeUpdate(); }
153
6.5.4 Invullen van een ArrayList met de waarden uit de ‘bothOK’-kolom In onderstaande code wordt naar de gebruiker toe weergegeven met welke meter gewerkt wordt. Zijn aantal elementen wordt eveneens met de methode ‘last’ berekend en aan de gebruiker getoond. Vervolgens kan met deze laatste waarde in een for-lus de ArrayList ‘bothOK’ gevuld worden met de waarden uit de ‘bothOK’-kolom. Hiervoor wordt de methode ‘fill_bothOK’ gebruikt die later uitgelegd wordt. Deze waarden zijn namelijk noodzakelijk voor het verdere verloop van het programma. for (int aa = 0; aa <= a; aa++) { String meter = inputs.get(aa); System.out.println("----------------------------------------------"); System.out.println("Meter: "+ meter); System.out.println("----------------------------------------------"); String str = "SELECT max(idMeter) as maximum FROM `"+date+"`.`sncb logistics--"+meter+"`"; rs1 = statement.executeQuery(str); int maximum = last(rs1); System.out.println("meter maximum: " + maximum); for(int k = 1; k<= maximum; k++) { String str2 = "SELECT bothOK FROM `"+date+"`.`sncb logistics--"+meter+"` WHERE idMeter = "+k; rs2 = statement.executeQuery(str2); fill_bothOK(rs2); }
6.5.5 Invullen van de resterende ArrayLists Nadat de ArrayList ‘bothOK’ is ingevuld, kan uit deze lijst alle verschillende treinritten gehaald worden. In deze lijst kunnen drie soorten waarden voorkomen, namelijk:
Een ‘null’-waarde. Een enkele treinrit, bijvoorbeeld ‘46255’. Meerdere treinritten gescheiden door een koppelteken, bijvoorbeeld ‘46255-1827’ of ‘46255-741-43732’.
Als het om een ‘null’ gaat, dan moet er niets gebeuren. De ArrayList ‘bothOK’ wordt aan de hand van een for-lus doorlopen. Als het niet om een ‘null’-waarde gaat (eerste if-lus), moet er gekeken worden of het om een enkele treinrit of meerdere treinritten gaat. Hiervoor wordt gekeken of de String die in de ArrayList is opgeslagen een koppelteken bevat (tweede if-lus). In de tweede for-lus worden vervolgens de begin- en eindpositie van een treinritnummer gezocht. Dit gebeurt in de if-lus die genest is in deze for-lus. Aan de hand van deze posities kan de treinrit dan afgezonderd worden en opgeslagen worden als een afzonderlijke String. Met behulp van de methode ‘find’, die als argument dit treinritnummer krijgt, worden vervolgens de ArrayLists met de treinritten en hun totale en distinctieve totale aantal 154
bijgevuld en/of aangepast. Deze methode komt later nog aan bod. De if-lus waar daarnet sprake over was (en die genest is in de tweede for-lus) werkt enkel met de treinritten die zich voor een koppelteken bevonden. De else-if-component hiervan houdt zich bezig met de treinrit na het laatste koppelteken en werkt eveneens met de methode ‘find’. Als de String in de lijst geen koppelteken bevat, wordt naar de else-component van de tweede if-opdracht gegaan. Aangezien er geen koppelteken is, is er slechts één treinrit ingevuld. Deze wordt dan aan de methode ‘find’ opgegeven. Elke keer nadat de methode ‘find’ werd opgeroepen, wordt daarna de ArrayList ‘temporary’ aangevuld met dezelfde treinrit die aan de methode was meegegeven. Deze ArrayList zorgt ervoor dat in de methode ‘find’ het distinctieve aantal kan berekend worden. Het principe hierachter is dat wanneer een treinrit meerdere malen voorkomt, hij ook in deze ArrayList meerdere malen wordt opgeslagen. In de methode ‘find’ wordt vervolgens gekeken als deze treinrit al in de lijst aanwezig is. Indien dit zo is, dan wordt het aantal niet met één vermeerderd, anders wel. Om deze reden wordt de treinrit pas na de methode ‘find’ aan ‘temporary’ toegevoegd, zodat bij het eerste voorkomen van de treinrit het distinctieve aantal wel vermeerderd wordt en daarna niet meer. Tenslotte wordt de methode ‘order’ aangeroepen die de drie lijsten met de treinritnummers en hun aantallen ordent in drie nieuwe lijsten. Over deze methode wordt later meer uitleg gegeven. for(int i = 0; i < bothOK.size(); i++) { int start_position; int stop_position = -2; if(bothOK.get(i) != null) { String element = bothOK.get(i); if(element.contains("-")) { char stripe = '-'; int length = element.length(); for(int j = 0; j < length; j++) { if(element.charAt(j) == stripe) { start_position = stop_position + 2; stop_position = j - 1; String train_number = element.substring(start_position, stop_position + 1); find(train_number); temporary.add(train_number); } else if(j == length - 1)
155
{ start_position = stop_position + 2; String train_number2 = element.substring(start_position); find (train_number2); temporary.add(train_number2); } } } else { find(element); temporary.add(element); } } temporary.clear(); } order();
6.5.6 De kolom ‘propose’ invullen in de tabel van de databank In onderstaande code wordt eerst via SQL het aantal elementen gevraagd uit de ‘bothOK’kolom van de databanktabel. Deze wordt dan in Java met behulp van de methode ‘last’ opgeslagen. De reden waarom deze waarde nodig is, werd eerder al uitgelegd, namelijk om te kunnen zien wanneer het cumulatieve distinctieve aantal deze waarde overschrijdt. De methode ‘propose_position’ krijgt als argument deze waarde mee en zal op basis van de geordende lijsten de positie teruggeven van de laatste kandidaat-treinrit die naar Erex als nieuw voorstel mag gestuurd worden (in de voorbeeldtabel zou dit dus overeenkomen met de positie van het treinnummer met de laatste ‘x’). In deze methode wordt deze positie gevonden door het cumulatieve distinctieve aantal te vergelijken met de waarde die via SQL verkregen werd. Dit wordt later nog verder uitgediept. Vervolgens wordt in een for-lus, die de elementen van de ‘bothOK’-kolom van de databanktabel doorloopt, de methode ‘propose_fill’ opgeroepen. In deze methode wordt de uiteindelijke selectie aan kandidaat-treinritten in de kolom ‘propose’ van de databanktabel toegevoegd. Dit wordt niet rechtstreeks gedaan, de methode geeft echter een String terug. Deze String wordt vervolgens in de hoofdmodule naar de databank doorgevoerd via de ifelse-structuur. In het if-gedeelte gebeurt er niets (bijvoorbeeld wanneer de ‘bothOK’-kolom een ‘null’-waarde heeft of wanneer één van de eindkandidaten niet in de ‘bothOK’-kolom voorkomt) en in het else-gedeelte wordt de databanktabel aangevuld met het treinritnummer dat bij een bepaald meterelement hoort. Tenslotte worden alle combinaties energiemeter – treinritnummer weergegeven die naar Erex als nieuwe voorstellen zullen gezonden worden. De ArrayLists worden geledigd zodat ze gebruikt kunnen worden voor de volgende energiemeter. Als alle energiemeters doorlopen
156
zijn, wordt ook de ArrayList ‘inputs’ geledigd. Deze lijst bevat alle energiemeters waarmee gewerkt werd. String str3 = "SELECT count(idMeter) as maximum FROM `"+date+"`.`sncb logistics--"+meter+"` where bothOK is not null"; rs3 = statement.executeQuery(str3); int without_null = last(rs3); int pp = propose_position(without_null); for(int kkk = 1; kkk<= maximum; kkk++) { String str4 = "SELECT bothOK FROM `"+date+"`.`sncb logistics--"+meter+"` WHERE idMeter = "+kkk; rs4 = statement.executeQuery(str4); String update = propose_fill(pp, rs4, date, meter, kkk); if(update.equals("")) { } else { pstmt2 = con.prepareStatement(update); pstmt2.executeUpdate(); } } System.out.println("The new combinations meter - train number are:"); for(int print = 0; print <= pp; print ++) { System.out.println(meter + " --- " + ordered_train_nrs.get(print)); } bothOK.clear(); train_nrs.clear(); amount.clear(); amount_distinct.clear(); ordered_train_nrs.clear(); ordered_amount.clear(); ordered_amount_distinct.clear(); } inputs.clear(); }
6.5.7 Afsluiten van het programma Uiteindelijk wordt het programma afgesloten. Dit is analaag aan de voorgaande programma’s en wordt in onderstaande code getoond. 157
catch (Exception e) { throw e; } finally { if (con != null) { con.close(); } if (pstmt != null) { pstmt.close(); } if (pstmt2 != null) { pstmt2.close(); } if (rs1 != null) { rs1.close(); } if (rs2 != null) { rs2.close(); } if (rs3 != null) { rs3.close(); } if (rs4 != null) { rs4.close(); } if (statement != null) { statement.close(); } } System.out.println("Done."); }
6.5.8 Methode last Deze methode krijgt van de databank een waarde en deze waarde wordt in deze methode als geheel getal opgeslagen. Deze methode kwam ook al eerder aan bod bij de vorige programma’s en is volledig hetzelfde. static int last(ResultSet rs1) throws SQLException { int getal = 0; while (rs1.next()) { getal = rs1.getInt("maximum");
158
} return getal; }
6.5.9 Methode fill_bothOK Deze methode krijgt telkens één waarde uit de ‘bothOK’-kolom van de databanktabel en vult deze waarde vervolgens in de corresponderende ArrayList aan. Indien het om een ‘null’waarde gaat, wordt ‘null' toegevoegd, zoniet wordt de String-waarde uit de kolom toegevoegd. static void fill_bothOK(ResultSet rs2) throws SQLException { while (rs2.next()) { String bOK = rs2.getString("bothOK"); if(bOK == null) { bothOK.add(null); } else { bothOK.add(bOK); } } }
6.5.10 Methode find Deze methode krijgt een welbepaald treinritnummer mee als argument. Als de lijst ‘train_nrs’ leeg is dan betekent dit dat er nog geen enkel treinritnummer werd toegevoegd. Het meegegeven nummer kan dan toegevoegd worden in die lijst (eerste if-opdracht). Zijn totale aantal komt op één te staan en zijn distinctieve totale aantal wordt eveneens één. De boolean ‘check’ die in het begin als ‘false’ werd gedeclareerd, wordt nu ‘true’. De reden waarom dit nodig is, wordt later duidelijk. Is de lijst ‘train_nrs’ niet leeg, dan wordt de else-component aangesproken. Deze niet lege lijst wordt via een for-lus doorlopen. De if-opdracht die hierin staat, kijkt als de treinrit, die meegegeven was als argument, al in de lijst ‘train_nrs’ staat. Indien dit zo is dan wordt het totale aantal met één vermeerderd in de lijst ‘amount’. In de for-lus die daarop volgt, wordt het distinctieve totale aantal eventueel aangepast. Hiervoor wordt er een vergelijking met de lijst ‘temporary’ doorgevoerd. Als het treinritnummer zich al in deze lijst bevindt, dan betekent dit dat het al eerder is voorgekomen in het ‘bothOK’-element waarmee momenteel gewerkt wordt. In dat geval mag het distinctieve totale aantal niet vermeerderd worden. Als het nummer eerder al voorkwam, dan wordt de integer ‘e’ die als nul gedeclareerd was, vermeerderd. Vervolgens wordt in een if-lus deze waarde bekeken. Als ‘e’ nog steeds nul is, 159
dan betekent dat het treinritnummer nog niet eerder is voorgekomen en mag het distinctieve totale aantal dus met één vermeerderd worden. De boolean ‘check’ wordt vervolgens ook op ‘true’ gezet. Als in de laatste if-opdracht de boolean ‘check’ nog steeds ‘false’ is, dan betekent dit dat de lijst ofwel niet leeg was en het nummer hier dus ook niet aan toegevoegd is (eerste ifopdracht) of het betekent dat het treinritnummer nog niet in de reeds gevulde lijst met nummers voorkwam. Daarom mag dit nummer aan de lijst toegevoegd worden en zijn beide totalen op één gezet worden. static void find(String TN) { int b; boolean check = false; if(train_nrs.isEmpty()) { train_nrs.add(TN); amount.add(1); amount_distinct.add(1); check = true; } else { int a = train_nrs.size(); for(int k = 0; k < a; k++) { if(TN.equals(train_nrs.get(k))) { b = amount.get(k) + 1; amount.set(k,b); int c = temporary.size(); int e = 0; for(int d = 0; d < c; d++) { if(TN.equals(temporary.get(d))) { e++; } } if(e == 0) { int f = amount_distinct.get(k) + 1; amount_distinct.set(k,f); } check = true; } } if(check == false) { train_nrs.add(TN); amount.add(1); amount_distinct.add(1); }
160
} }
6.5.11 Methode order In de methode ‘order’ worden de drie “ordered” lijsten aangevuld. Er wordt hier geordend op basis van het totale aantal en niet het distinctieve totale aantal. Dit wordt gedaan totdat alles geordend is (while-lus). In het begin wordt de else-lus aangesproken. De integer ‘max’ wordt op nul gezet. Vervolgens wordt een for-lus doorlopen die alle treinritnummers in de ArrayList ‘train_nrs’ doorloopt. In deze lus wordt het maximum genomen van de integer ‘max’, de waarde van het totale aantal aan het einde van de ‘amount’-lijst en de waarde dat in deze lijst op de positie, aangegeven door de iteratie van de for-lus, staat. De waarde van ‘max’ wordt dus continu overschreden totdat alle waarden vergeleken zijn en dus het echte maximum bekomen wordt. Vervolgens wordt de boolean ‘found’ gedeclareerd en krijgt het de waarde ‘false’. De integer ‘zz’ wordt eveneens gemaakt en wordt op nul gezet. In de while-lus die daarop volgt, wordt het maximum dat daarnet gevonden was, in de ‘amount’-lijst gezocht. Als deze waarde gevonden is, dan betekent dit dat de hoogste waarde in de lijst gevonden is. Deze waarde mag dan in de geordende lijst komen. Daarom wordt het corresponderende treinritnummer en zijn distinctieve totale aantal samen met dit totale aantal in de lijsten toegevoegd. Aangezien de ordening nog niet gedaan is, worden deze drie waarden uit de niet geordende lijsten geschrapt zodat bij het zoeken naar de volgende maximale waarde niet dezelfde waarde gekozen wordt. De boolean ‘found’ wordt nu ‘true’ waardoor de while-lus stopt. De ‘zz’ waar daarnet sprake over was, wordt gebruikt voor het doorlopen van de niet geordende lijsten totdat de maximale waarde gevonden is. Daarom wordt na elke iteratie deze waarde met één vermeerderd, zodat de volgende waarde in de lijst kan vergeleken worden op een overeenkomst met de maximale waarde. Als dit gebeurd is, dan wordt de eerste while-lus herhaald en dit todat alle waarden uit ‘train_nrs’ verwijderd zijn of dus totdat alle waarden in de geordende lijsten geordend zitten. Wanneer de lijst ‘train_nrs’ nog maar één waarde bevat, dan heeft het geen nut meer te zoeken naar het maximum van de resterende waarden in deze lijst aangezien er slechts één waarde in zit. Deze treinrit mag dus met zijn corresponderende totale aantal en distinctieve totale aantal direct in de geordende lijsten gezet worden. Hiermee is het laatste treinritnummer met het kleinste totale aantal en zijn bijhorende distinctieve totale aantal op de laatste positie van de geordende lijsten geplaatst. static void order() { while(!(train_nrs.isEmpty())) { if(train_nrs.size() == 1) { ordered_train_nrs.add(train_nrs.get(0)); train_nrs.remove(0); ordered_amount.add(amount.get(0));
161
amount.remove(0); ordered_amount_distinct.add(amount_distinct.get(0)); amount_distinct.remove(0); } else { int max = for(int z { int int int
0; = train_nrs.size()-2; z > -1 ; z--) size_list = train_nrs.size(); amount1 = amount.get(size_list - 1); amount2 = amount.get(z);
max = Math.max(max, Math.max(amount1, amount2)); } boolean found = false; int zz = 0; while(found == false && zz < train_nrs.size()) { if(amount.get(zz) == max) { found = true; ordered_train_nrs.add(train_nrs.get(zz)); train_nrs.remove(zz); ordered_amount.add(amount.get(zz)); amount.remove(zz); ordered_amount_distinct.add(amount_distinct.get(zz)); amount_distinct.remove(zz); } zz++; } } } }
6.5.12 Methode propose_position In deze methode wordt de positie gezocht van het treinritnummer met zijn corresponderende totale aantal en distinctieve totale aantal waarbij de som van het distinctieve totale aantal van dit element en al zijn voorgangers in de geordende lijst niet groter is dan de waarde meegegeven als parameter aan deze methode. Deze positie is nodig om het kaf van het koren te scheiden. Zo worden de voornaamste kandidaten geselecteerd en kunnen deze als nieuwe voorstellen naar Erex gestuurd worden. In een lijst wordt de eerste positie weergegeven door nul en niet door één. Daarom wordt na de while-lus, die blijft doorgaan tot de meegegeven parameter overschreden wordt, de positie met twee verminderd. De positie die op het einde van de while-lus bekomen is, is die van het element dat voor de overschrijding zorgt en deze mag niet mee gerekend worden, dit zorgt 162
dus voor een eerste vermindering met één. Omdat de posities niet vanaf één, maar vanaf nul beginnen, dient er nog een extra aftrekking te gebeuren. Dit zorgt voor een totaal van -2. static int propose_position(int wn) { int border = 0; int position = 0; int size = ordered_train_nrs.size(); int add; while(border <= wn && position < size) { add = ordered_amount_distinct.get(position); border = border + add; position++; } position = position - 2; return position; }
6.5.13 Methode propose_fill In deze laatste methode wordt de kolom, die in het begin van het programma aan de databanktabel was toegevoegd, ingevuld met de kandidaat-treinritten die uiteindelijk overgebleven zijn na de shifting. Deze shifting gebeurde door de som van de distinctieve totale aantallen geordend volgens de totale aantallen continu te vergelijken met het aantal ingevulde bothOK-rijen tot deze som deze laatste waarde overschreed (zie eerdere uitleg). Hierbij worden deze eindkandidaten die tot een bepaalde positie in de drie geordende lijsten staan (deze positie is als parameter meegegeven en was berekend in de methode ‘propose_position’) vergeleken met de elementen van de kolom ‘bothOK’. Als een rij van de ‘bothOK’-kolom niet ‘null’ is en één van de kandidaat-treinritten bevat, dan wordt deze aan de ‘propose’-kolom toegevoegd. Dit gebeurt niet rechtstreeks. In deze methode wordt slechts de String opgesteld met het SQL-commando. Deze String wordt vervolgens aan de hoofdmodule gegeven waar het SQL-commando uiteindelijk uitgevoerd wordt. De eerste for-lus in onderstaande code doorloopt het aantal elementen, die als eindkandidaten gelden, in de geordende lijsten. Hierbij wordt achterwaarts vertrokken, dus van de minst waarschijnlijke eindkandidaat naar de meest waarschijnlijke eindkandidaat. In de if-opdracht die daarop volgt (als de ‘bothOK’-waarde niet ‘null’ is), wordt gekeken of de ‘bothOK’-waarde de treinrit bevat die aangegeven is door de iteratie van de for-lus in de geordende lijsten. Indien dit zo is, wordt deze treinrit in de String ‘nw’ opgeslagen. Deze String werd in het begin als leeg (of “”) gedeclareerd. De treinrit wordt hier dus aan toegevoegd. Het kan gebeuren dat meerdere van de eindkandidaten in een rij van de ‘bothOK’-kolom voorkomen. Als dit zo is, worden deze allemaal in de ‘propose’-kolom 163
weergegeven, maar gescheiden met een koppelteken. Dit kan in de eerste else-opdracht hieronder teruggevonden worden. De String ‘nw’ wordt dus steeds overschreden totdat alle mogelijke treinritten erin staan. Deze String wordt toegevoegd aan een andere String, namelijk ‘change’. Deze bevat het SQLcommando dat terug aan de hoofdmodule wordt gegeven. Als er geen treinritten in de rij van de ‘bothOK’-kolom voorkomen of deze rij ‘null’ is (laatste else-component), dan blijft ‘change’ leeg. Als deze lege waarde aan de hoofdmodule wordt teruggegeven, dan zal de ‘propose’-kolom niet aangepast worden. static String propose_fill(int pos, ResultSet rs3, String date, String meter, int kkk) throws SQLException { String change = ""; String nw = ""; while (rs3.next()) { String bOK = rs3.getString("bothOK"); for (int i = pos; i >= 0; i--) { if(bOK != null) { if(bOK.contains(ordered_train_nrs.get(i))) { if(nw.equals("")) { nw = ordered_train_nrs.get(i); } else { nw = nw + "-" + ordered_train_nrs.get(i); } change = "UPDATE `"+date+"`.`sncb logistics--"+meter+"` SET `propose`='"+nw+"' WHERE `idMeter`='"+kkk+"';"; } } else { change = ""; } } } return change; } }
6.5.14 Lopen van het programma
164
Vooraleer het programma gelopen heeft, ziet de tabel van een meter er uit zoals op onderstaande afbeelding. In de ‘bothOK’-kolom komen alle kandidaten voor.
Figuur 127: De tabel van een meter voor het lopen van het derde deel van het hoofdprogramma
Op onderstaande afbeelding wordt het lopende programma weergegeven. Het programma toont voor elke meter de belangrijkste combinaties met een treinritnummer. Deze combinaties zullen dan in Erex verder gecontroleerd moeten worden aan de hand van de resterende validatieregels.
165
Figuur 128: Lopen van het derde deel van het hoofdprogramma
Op het einde van het derde deel van het hoofdprogramma wordt wederom “Done.” naar de gebruiker toe weergegeven. Dit is hieronder geïllustreerd.
166
Figuur 129: Einde van het derde deel van het hoofdprogramma
Als er na het lopen van het derde deel van het hoofdprogramma gekeken wordt naar dezelfde tabel, dan kan in de ‘propose’-kolom de uiteindelijke eindkandidaten teruggevonden worden. Dit wordt op onderstaande afbeelding weergegeven. Deze extra kolom is in principe niet nodig aangezien de combinaties al gekend zijn en in het programma worden weergegeven, maar het is een handig hulpmiddel om te zien met welke meterelementen deze treinritten overeenkomen.
167
Figuur 130: Tabel van een meter na het lopen van het derde deel van het hoofdprogramma
In principe zullen er net genoeg of teveel eindkandidaten gevonden worden. Dit is niet erg aangezien er beter teveel kandidaten gevonden worden waarna de foute kandidaten er later door Erex uit gefilterd worden aan de hand van de validatieregels. Met het gevonden aantal eindkandidaten (die dus in de ‘propose’-kolom verschijnen) kan in het programma nog gespeeld worden door in de methode ‘propose_position’ de voorwaarden van de while-lus aan te passen. Zo kunnen er nog meer of minder eindkandidaten bekomen worden als er daar wens naar is. Het probleem hierbij is dat wanneer er minder kandidaten bekomen zullen worden, er een kans bestaat dat goede eindkandidaten verloren gaan en wanneer er meer kandidaten bekomen wordt, dan heeft Erex meer validatiewerk. De manier waarop het nu geprogrammeerd staat, is dus de meest optimale wijze.
168
Hoofdstuk 7: Bespreking van de resultaten 7.1
Gevonden combinaties
Infrabel beschikt over een webapplicatie genaamd ‘Artweb’. Deze applicatie beschikt over een archief waarin alle treinritten, gedetecteerd door de detectiepunten, opgeslagen worden. Er kunnen zowel gegevens opgevraagd worden op vlak van treinritnummer of op basis van station. Deze gegevens zijn praktisch dezelfde als degene die door de applicatie IVET naar Erex worden gestuurd. Op onderstaande afbeelding worden de gegevens van een treinrit met een welbepaald treinritnummer op een gekozen dag in Artweb weergegeven.
Figuur 131: Treinritgegevens opgevraagd in Artweb
De resultaten van het hoofdprogramma kunnen manueel gecontroleerd worden met behulp van deze Artweb-gegevens. Wanneer op de webapplicatie van Erex het traject van een energiemeter opgevraagd wordt, kan deze in Artweb vergeleken worden met het traject van de treinritnummers die het programma heeft voorgesteld. Op onderstaande afbeelding wordt de webapplicatie van Erex weergegeven. Hierbij worden de coördinaten van en een map met het metertraject weergegeven.
169
Figuur 132: Traject van een energiemeter in de webapplicatie van Erex
Wanneer de combinaties van elke energiemeter met zijn voorgestelde treinritnummers gecontroleerd worden op basis van tijd en locatie, dan kan geconcludeerd worden dat de gevonden treinritten inderdaad bij de energiemeter passen. Er werd al eerder vermeld dat er bij sommige meters teveel combinaties met treinritnummers werden voorgesteld. Wanneer deze combinaties manueel gecontroleerd worden dan valt op dat dit meestal om slecht een heel klein deeltraject gaat dat overeenkomt. Deze combinaties zullen dan ook later door Erex afgekeurd worden op basis van de validatieregels. Na de controle door Erex zullen dus enkel de juiste combinaties overblijven. Het kan voorkomen dat bij de gevonden voorstellen er geen waarde is opgegeven in de ‘propose’-kolom (‘null’). Indien het om een of enkele null-waarden tussen allemaal dezelfde treinritnummers gaat, dan betekent dit dat deze lege waarden eveneens bij deze treinrit horen. De uitleg hiervan werd eerder al gedaan, namelijk dat het kan voorkomen dat een 170
energiemeter er minder lang over doet dan vijf minuten om tussen twee detectiepunten te rijden en hier dus geen energiewaarde bij opneemt. De energiemeter hoort wel degelijk tot dat traject en de koppeling met die treinrit is dus juist. Het kan ook gebeuren dat er een langere opeenvolging van null-waarden voorkomt en dat er dus geen koppeling met een treinrit gevonden is. In dat geval wordt er gesproken van een losse treinrit. Een losse treinrit kan bijvoorbeeld gebeuren wanneer een locomotief los gekoppeld wordt en verplaatst wordt voor verder gebruik in een andere treinrit. Tijdens deze verplaatsing wordt de locomotief dus niet gebruikt door één van de klanten van Infrabel. Zo’n losse treinrit wordt door de medewerkers van de spoorwegen niet ingegeven als een treinrit en een koppeling met zo’n treinrit zal dus ook niet mogelijk zijn. Deze opeenvolging van nullwaarden is dus niet foutief, maar representeert gewoon een losse treinrit. Het doel van het hoofdprogramma, namelijk de juiste combinaties van een energiemeter met één of meerdere treinritten vinden, is dus verwezenlijkt.
7.2
Tijd
Het probleem bij het doorzoeken van een volledige database en het verwerken van de gegevens hiervan is dat het tijdsverloop hierbij kan oplopen. Bij een eerste versie van het tweede deel van het hoofdprogramma had het programma meer dan negen uur nodig om tot de voorstellen te komen. Er is hier sprake van meer dan negen uur omdat het programma nooit volledig doorlopen is geweest. Omdat het tijdsverbruik al zo hoog opliep, werd het programma handmatig gestopt. Omdat een dergelijke tijdsduur onacceptabel is, werd het principe achter het programma veranderd. Oorspronkelijk werden de gegevens van de meter in een ArrayList opgeslagen. Deze gegevens werden dan vergeleken met de tms-data die rechtstreeks uit de databank werd opgevraagd. Bij een tweede versie van het tweede deel van het hoofdprogramma werd hetzelfde principe gehanteerd, nu werd echter wel in het sql-commando voor het opvragen van de tms-data een where-clausule toegevoegd die het aantal gegevens limiteerde. Nadat het programma voor de eerste keer liep, werd terug een zelfde programmalooptijd behaald als bij de eerste versie. Aangezien het steeds opnieuw opvragen van gegevens uit de databank nogal tijdrovend was, werd voor een nieuwe manier van handelen gekozen. De tms-data kon wegens geheugenproblemen (dit werd eerder al vermeld) niet in zijn totaliteit in een ArrayList opgeslagen worden. Daarom werd in beurten gewerkt. Er werd dus steeds een deel van de tms-data in de lijsten ingeladen om vervolgens een vergelijking met de lijsten met de energiemetergegevens te ondergaan. Hierna werden de tms-lijsten geledigd en gevuld met een volgend deel. De uiteindelijke uitvoertijd van het programma bedroeg twee uur en veertig minuten, wat een hele verbetering is ten opzichte van de tijdsduur die oorspronkelijk werd behaald. Dit tijdsverloop zal uiteraard per dag variëren. Deze tijd wordt bepaald door het aantal meters dat die dag niet toegewezen werd en eveneens de kwantiteit aan gegevens waarover elke meter beschikt. Voor een meter met zestig gegevens mag een uitvoertijd van zeventien minuten gerekend worden. 171
Het programma dat een tijdsduur van twee uur en veertig minuten haalde, werd in hoofdstuk zes besproken. Het gaat hier enkel om het tweede deel van het hoofdprogramma. Het eerste en derde deel hadden slechts enkele seconden nodig om tot hun einde te komen, wat uiteindelijk een totale tijdsduur geeft van twee uur en veertig minuten.
7.3
Eventuele aanvullingen
Hoe Erex intern werkt, is een geheim. Dit is logisch aangezien men de code hiervan niet zomaar aan derden zal geven. Voor deze thesis was het dus zeker een uitdaging een aanvullend programma hierbij te schrijven. Op basis van hoe Erex exact werkt, kan met de output van het hoofdprogramma enkele aanvullingen gedaan worden. Zo kunnen bijvoorbeeld de null-waarden in de propose-kolom (niet de losse treinritten) opgevuld worden op basis van de waarden die ervoor en erna komen. Indien meerdere treinritten in dezelfde rij van de propose-kolom voorkomen, kunnen de minst relevante verwijderd worden op basis van de enkele treinritwaarden die daarvoor en daarna komen. Zo kan men aaneensluitende blokken van treinritten bekomen. Hierbij kan dan bijvoorbeeld het energieverbruik en/of -teruggave van ieder blokelement, die in dezelfde tabel teruggevonden kan worden, steeds opgeteld worden om aan het einde van zo’n blok uiteindelijk het totale verbruik van zo’n treinrit te bekomen. Op deze manier kunnen ook deeltrajecten gefactureerd worden aangezien Erex momenteel een alles of niets regel heeft en dus geen facturatie, op basis van deeltrajecten die overeenkomen met meters, toelaat.
172
Algemeen besluit Na de resultaten van het hoofdprogramma gecontroleerd te hebben, kan geconstateerd worden dat het mogelijk is om aan Erex een aanvulling toe te voegen zodat afgewezen energiemeters toch nog gekoppeld kunnen worden aan één of meerdere treinritten. Hierdoor kunnen nauwkeurigere facturen voor de klanten van Infrabel opgesteld worden. Het grootste probleem hierbij is echter de tijd die hiervoor nodig is. Het is al gelukt dit tijdsverloop in te korten naar twee uur en veertig minuten voor de afgewezen energiemeters van 25 september 2013. Dit tijdsverloop zal uiteraad per dag verschillen en afhangen van het aantal niet toegewezen meters per dag (voor 25 september stond de teller van dit aantal op vier). Ook de tijd die het programma voor elke meter apart nodig heeft varieert, een meter met zestig gegevens heeft ongeveer zeventien minuten nodig en bij een meter met meer dan tweehonderd gegevens zal deze tijdsduur uiteraard hoger liggen. De eventuele implementatie van een programma zoals het in deze thesis aan bod komt, zal afhangen van de medewerkers van Erex. Zij zullen verder moeten bepalen als zo’n tijdsverloop acceptabel is en als het toevoegen van een extra programma aan Erex haalbaar is. Aangezien in de toekomst alle treinen van meters voorzien zullen zijn, zal de uitvoertijd van het hoofdprogramma nog oplopen. In deze thesis werd er ook enkel gewerkt met de gegevens van de klant ‘SNCB Logistics’ omdat zij op dit moment over het grootste deel energiemeters beschikken. Er dient echter wel rekening gehouden te worden met het feit dat alle programma’s geschreven en uitgevoerd zijn op een vijf jaar oude laptop. De snelheid van een hedendaagse computer zal uiteraard veel hoger zijn, zeker wanneer er een computer, die ontworpen is om met databanken te werken, gebruikt wordt.
173
Lijst met figuren en tabellen Figuren Figuur 1: De structuur van de NMBS-groep (NMBS-holding, z.j.)..........................................................7 Figuur 2: Pantograaf (Stroomafnemer, z.j.) .........................................................................................8 Figuur 3: Overzicht van de afgelegde weg van de tractie-energie (Cel energiebeheer, 2012) ...............9 Figuur 4: Drie keten langs de spoorwegen in de nabijheid van het station van Brugge....................... 10 Figuur 5: Energiemeter (links) en zijn stroom- en spanningsmeting (rechts) ...................................... 12 Figuur 6: Het logo van Eress en Erex (eress, z.j.) ................................................................................ 13 Figuur 7: Flow van gegevens naar Erex .............................................................................................. 14 Figuur 8: Algoritme met het algemeen overzicht ............................................................................... 20 Figuur 9: Algoritme bij 'Payload and metered locations did not match' ............................................. 23 Figuur 10: Algoritme bij 'Payload and metered energy did not match' ............................................... 25 Figuur 11: Het bepalen van de rijzin bij assentellers (Van Hoyweghen, 2004) .................................... 27 Figuur 12: Detectieprincipe van de assenteller (Toelichting 15, 1998) ............................................... 28 Figuur 13: Principe achter de combinatie van twee assentellers ........................................................ 29 Figuur 14: Assenteller aan een rail in de nabijheid van het station Gent Sint-Pieters ......................... 29 Figuur 15: Verschillende secties en isolaties bij gewone SK's ............................................................. 30 Figuur 16: Distributie van tractiestroom (Module 0.1, 2010) ............................................................. 31 Figuur 17: Overbruggen van de isolaties............................................................................................ 32 Figuur 18: Gebruik van een spoel in de nabijheid van het station Gent Sint-Pieters ........................... 33 Figuur 19: Principe van een gewone spoorstroomkring (Toelichting 5, z.j.) ........................................ 34 Figuur 20: Geheel van gesloten stroomcircuit en spoorstroomkring .................................................. 35 Figuur 21: Serieresonantie (Basis elektronica deel 5, 2011) ............................................................... 36 Figuur 22: Stroomsterkte in functie van de frequentie bij serieresonantie (Resonantiegedrag, 2010) 37 Figuur 23: Parallelresonantie (Basis elektronica deel 5, 2011) ........................................................... 37 Figuur 24: Serieresonantie bij 2200 Hz (impedantie) ......................................................................... 38 Figuur 25: Serieresonantie bij 2200 Hz (stroom) ................................................................................ 38 Figuur 26: Serieresonantie bij 2200 Hz (faseverschuiving) ................................................................. 39 Figuur 27: Serieresonantie bij 1600 Hz (impedantie) ......................................................................... 39 Figuur 28: Serieresonantie bij 1600 Hz (stroom) ................................................................................ 40 Figuur 29: Serieresonantie bij 1600 Hz (faseverschuiving) ................................................................. 40 Figuur 30: Parallelresonantie bij 2200 Hz (impedantie)...................................................................... 41 Figuur 31: Parallelresonantie bij 2200 Hz (stroom) ............................................................................ 41 Figuur 32: Parallelresonantie bij 2200 Hz (faseverschuiving) ............................................................. 42 Figuur 33: Parallelresonantie bij 1600 Hz (impedantie)...................................................................... 42 Figuur 34: Parallelresonantie bij 1600 Hz (stroom) ............................................................................ 43 Figuur 35: Parallelresonantie bij 1600 Hz (faseverschuiving) ............................................................. 43 Figuur 36: Schema van twee sporen in De Pinte ................................................................................ 44 Figuur 37: Codes bij de jade spoorstroomkringen (Toelichting 5 bundel 5, 2001) .............................. 45 Figuur 38: Algemeen overzicht van een jade spoorstroomkring met zender en ontvanger (Toelichting 5 bundel 5, 2001) .............................................................................................................................. 46 Figuur 39: Schema van de spoorfilters (Toelichting 5 bundel 5, 2001) ............................................... 47 Figuur 40: Blokkeerfilter afgestemd op f1 (Toelichting 5 bundel 5, 2001) .......................................... 47 174
Figuur 41: Blokkeerfilter afgestemd op f2 (Toelichting 5 bundel 5, 2001) .......................................... 48 Figuur 42: Schema van twee sporen in De Pinte (groter) ................................................................... 49 Figuur 43: Volledig overzicht van de jade spoorstroomkringen.......................................................... 50 Figuur 44: Vergelijking van een spoorstroomkring en een assenteller (Toelichting 5 bundel 7, 1996) 51 Figuur 45: Energiemeting (Jans, 2009) ............................................................................................... 52 Figuur 46: Overzicht van de energiemeting (Railway Current & Voltage Transducers, 2011) .............. 53 Figuur 47: Blokschema spanningsomvormer (DV series Voltage Transducer: Insulated High Voltage measurements, 2008) ....................................................................................................................... 54 Figuur 48: De fluxgate meet de resulterende flux (Pollefliet, 2011) ................................................... 55 Figuur 49: Stroom en spanning in de fluxgate-spoel zonder primaire stroom (Pollefliet, 2011) .......... 55 Figuur 50: Stroom en spanning in de fluxgate-spoel bij een primaire stroom (Pollefliet, 2011) .......... 56 Figuur 51: Fluxgate van LEM (Pollefliet, 2011) ................................................................................... 56 Figuur 52: Blokschema van de energiemeter (Jans, 2009) ................................................................. 57 Figuur 53: Digitaal analoog conversie (Jans, 2009) ............................................................................. 58 Figuur 54: Analoog digitaal conversie (Jans, 2009)............................................................................. 59 Figuur 55: Aliasing (Aliasing effects, z.j.) ............................................................................................ 59 Figuur 56: Opbouw ADC (Jans, 2009)................................................................................................. 60 Figuur 57: Sample & Hold (Jans, 2009) .............................................................................................. 61 Figuur 58: Samplen door middel van een dirac-impuls (Jans, 2009) ................................................... 61 Figuur 59: Voorbeeld van kwantisatie (Jans, 2009) ............................................................................ 62 Figuur 60: Principe van de sigma-delta ADC ...................................................................................... 63 Figuur 61: Flowchart van de sigma-delta ADC.................................................................................... 63 Figuur 62: Dubbele frequentie van het vermogen ten opzichte van de spanning en de stroom ......... 64 Figuur 63: Principe van het berekenen van het schijnbaar vermogen ................................................ 66 Figuur 64: Bol rondom de satelliet (GPS, z.j.) ..................................................................................... 67 Figuur 65: Ring tussen twee satellietbollen (GPS, z.j.) ........................................................................ 67 Figuur 66: Twee mogelijke punten op basis van gps (GPS, z.j.) ........................................................... 68 Figuur 67: Energieflow ...................................................................................................................... 69 Figuur 68: Informatieflow naar Erex .................................................................................................. 70 Figuur 69: Voeding van een keet ....................................................................................................... 72 Figuur 70: Verschillende PLP's in een keet ......................................................................................... 73 Figuur 71: Parameterkaarten van de PLP's ........................................................................................ 73 Figuur 72: Assentellerkast ................................................................................................................. 74 Figuur 73: Elektriciteitskasten in een keet ......................................................................................... 75 Figuur 74: EBP ................................................................................................................................... 75 Figuur 75: SSI's .................................................................................................................................. 76 Figuur 76: Transformator (36 kV AC / 11 kV AC) in het tractieonderstation van Brussel-Zuid ............. 76 Figuur 77: Kenplaat van deze transformator ..................................................................................... 77 Figuur 78: Opbouw van een databanktoepassing .............................................................................. 79 Figuur 79: Client-server model (Moreau, 2013) ................................................................................. 80 Figuur 80: Startscherm van MySQL Workbench ................................................................................. 82 Figuur 81: Startup / Shutdown .......................................................................................................... 82 Figuur 82: Invullen van het wachtwoord ........................................................................................... 83 Figuur 83: De running status van de database server ........................................................................ 83 Figuur 84: Menubalk van MySQL Workbench .................................................................................... 83 175
Figuur 85: Invullen van de naam van de databank ............................................................................. 84 Figuur 86: SQL bij het creëren van een databank ............................................................................... 84 Figuur 87: Voorbeeld_thesis is aan het overzicht toegevoegd ........................................................... 85 Figuur 88: Aanmaken van een tabel .................................................................................................. 85 Figuur 89: Instellingen van een tabel ................................................................................................. 86 Figuur 90: SQL-code achter het aanmaken van een tabel .................................................................. 86 Figuur 91: Weergeven van de tabel bananen .................................................................................... 87 Figuur 92: De lege tabel bananen ...................................................................................................... 87 Figuur 93: Invullen van de tabel en de SQL-code hierachter .............................................................. 88 Figuur 94: De ingevulde tabel bananen ............................................................................................. 88 Figuur 95: Selecteren van de eerste twee kolommen van de tabel .................................................... 89 Figuur 96: Ordenen van de tabel ....................................................................................................... 89 Figuur 97: Gebruik van de where-clausule......................................................................................... 90 Figuur 98: Het updaten van waarden in de tabel ............................................................................... 90 Figuur 99: De tabel na de update ...................................................................................................... 91 Figuur 100: Voorbeeld van een if-else-opdracht ................................................................................ 93 Figuur 101: Uitbreiding door een else if-opdracht ............................................................................. 94 Figuur 102: Afbeelden van de natuurlijke getallen 0 tot 20 met behulp van een for-lus ..................... 95 Figuur 103: Werking van een while- en do-while-lus ......................................................................... 97 Figuur 104: Werking van methodes ................................................................................................... 98 Figuur 105: Build Path ..................................................................................................................... 100 Figuur 106: Toevoegen van External Jars ......................................................................................... 101 Figuur 107: Pad naar Excel-bestand van energiemetergegevens ..................................................... 104 Figuur 108: Verschillende bladen van het Excel-bestand met de energiemetergegevens ................. 105 Figuur 109: De naam van de meter op positie A1 (kolom nul en rij nul) ........................................... 106 Figuur 110: Lopen van het programma voor de gemeten energie.................................................... 110 Figuur 111: De databank is nog niet verschenen ............................................................................. 111 Figuur 112: Na refresh verschijnt de databank en zijn tabellen........................................................ 111 Figuur 113: Gegevens van een energiemetertabel .......................................................................... 112 Figuur 114: OutOfMemoryError: Java heap space ........................................................................... 127 Figuur 115: Activeren van de Run Configurations in Eclipse ............................................................. 128 Figuur 116: Aanpassen van het geheugen in Run Configurations ..................................................... 129 Figuur 117: Lopen van het programma voor de TMS-data ............................................................... 130 Figuur 118: na refresh verschijnt de TMS-tabel ............................................................................... 130 Figuur 119: de TMS-tabel in de databank ........................................................................................ 130 Figuur 120: Tabel van een energiemeter voor het lopen van het hoofdprogramma: deel 1 ............. 134 Figuur 121: Lopen van het hoofdprogramma: deel 1 ....................................................................... 134 Figuur 122: Tabel van een energiemeter na het lopen van het hoofdprogramma: deel 1 ................ 135 Figuur 123: Detectiegebied met en zonder speling (herhaling) ........................................................ 136 Figuur 124: Het lopen van het hoofdprogramma: deel 2 ................................................................. 148 Figuur 125: Einde van het hoofdprogramma: deel 2 ........................................................................ 149 Figuur 126: De databank na het uitvoeren van het hoofdprogramma: deel 2 .................................. 150 Figuur 127: De tabel van een meter voor het lopen van het derde deel van het hoofdprogramma .. 165 Figuur 128: Lopen van het derde deel van het hoofdprogramma .................................................... 166 Figuur 129: Einde van het derde deel van het hoofdprogramma ..................................................... 167 176
Figuur 130: Tabel van een meter na het lopen van het derde deel van het hoofdprogramma ......... 168 Figuur 131: Treinritgegevens opgevraagd in Artweb ....................................................................... 169 Figuur 132: Traject van een energiemeter in de webapplicatie van Erex .......................................... 170
Tabellen Tabel 1: Zomer- en wintertijd in 2013 ............................................................................................. 108 Tabel 2: Voorbeeld van totale en distinctieve totale som ................................................................ 151 Tabel 3: Principe van het cumulatief distinctief aantal..................................................................... 151
177
Bronnen Cel Energiebeheer. (2012). Your Power: Tractie-energie. Brussel: Infrabel. NMBS-Holding. (z.j.). Wie zijn wij? Geraadpleegd op 28 november 2013 via http://www.despoorwegenwervenaan.be/who Stroomafnemer. (z.j.). Wikipedia. Geraadpleegd op 28 november 2013 via http://nl.wikipedia.org/wiki/Stroomafnemer Eress. (z.j.). Images. Geraadpleegd op 6 april 2014 via http://www.eress.eu/images/Eress_logo_blue.gif Toelichting 15 Bundel 1 Algemeenheden – Bijlage 7. (1998). Brussel: Infrabel. Module 0.1: Inleiding tot de seininrichting. (2010). Brussel: Infrabel. Toelichting 5 – Hoofdstuk I – Blad: 1. (z.j.). Brussel: Infrabel. Toelichting 5 – Bundel 5: Elektrische voegen. (2001). Brussel: Infrabel. Basis elektronica deel 5. (2011). Geraadpleegd op 7 april 2014 via http://www.breem.nl/fldbasis/pgbasis-05.htm Resonantiegedrag. (2010). Geraadpleegd op 7 april 2014 via http://optiloadingsvn.hzs.be/raf/cursuselektricteitpdf/elekned2/hfdst8.pdf Toelichting 5 – Bundel 7 – Bijlage 3. (1996). Brussel: Infrabel. Van Hoyweghen, A. (2004). Toelichting 15: Assentellers. Brussel: Infrabel. Railway Current & Voltage Transducers. (2011). Geraadpleegd op 10 april 2014 via http://www.lem.com/images/stories/files/Products/1-53_traction_trackside/cae130404_0_web_size.pdf DV series Voltage Transducer: Insulated High Voltage measurements. (2008). Geraadpleegd op 10 april 2014 via http://www.lem.com/images/stories/files/Products/1-53_traction_trackside/LEM_DV_Leaflet_9_9_08.pdf Jans, M. (2009). Energiemeting van elektrische tractie-eenheden. Brussel: Infrabel. Aliasing effects. (z.j.). Geraadpleegd op 10 april 2014 via http://zone.ni.com/images/reference/en-XX/help/370051V-01/aliasing_effects.gif GPS. (z.j.). Geraadpleegd op 10 april 2014 via http://www.uhasselt.be/Documents/uhasselt@school/lesmateriaal/verkeerskunde/GPS_cursust ekst.pdf Moreau, J. (2013). Gegevensbanken I & II: Relationele gegevensbanken. Gent: Universiteit Gent. 178
Pollefliet, J. (2011). Elektronische vermogencontrole. Gent: Academia Press.
179
Geraadpleegde literatuur Cel Energiebeheer. (2012). Your Power: Tractie-energie. Brussel: Infrabel. NMBS-Holding. (z.j.). Wie zijn wij? Geraadpleegd op 28 november 2013 via http://www.despoorwegenwervenaan.be/who Moreau, J. (2013). Gegevensbanken I & II: Relationele gegevensbanken. Gent: Universiteit Gent. Van der Spiegel, B. (1993). Doenbaarheidsstudie van de automatische correctie van assentellers, toegepast zowel in volle baan als in stationsroosters. Brussel: Infrabel. Toelichting 5 – Bundel 5: Elektrische voegen. (2001). Brussel: Infrabel. Verlinde, J. (2013). Cursus toestellen in het spoor. Gent: Infrabel. Basis elektronica deel 5. (2011). Geraadpleegd op 7 april 2014 via http://www.breem.nl/fldbasis/pgbasis-05.htm Resonantiegedrag. (2010). Geraadpleegd op 7 april 2014 via http://optiloadingsvn.hzs.be/raf/cursuselektricteitpdf/elekned2/hfdst8.pdf Van Hoyweghen, A. (2004). Toelichting 15: Assentellers. Brussel: Infrabel. Jans, M. (2009). Energiemeting van elektrische tractie-eenheden. Brussel: Infrabel. Current transducer ITC 2000-S/SP1. (2014). Geraadpleegd op 10 april 2014 via http://www.lem.com/docs/products/itc%202000-s%20sp1.pdf GPS. (z.j.). Geraadpleegd op 10 april 2014 via http://www.uhasselt.be/Documents/uhasselt@school/lesmateriaal/verkeerskunde/GPS_cursust ekst.pdf Dhoedt, B. (2009). Informatica: Java. Gent: Universiteit Gent. Pollefliet, J. (2011). Elektronische vermogencontrole. Gent: Academia Press.
180
Bijlage 1: cd Alle programma’s werden al besproken in hoofdstuk 6. In dat hoofdstuk werd elk programma afzonderlijk in stukken uitgelegd. Aangezien de programma’s omvangrijk zijn, worden ze hier niet in de bijlage herhaald maar kunnen ze in hun totaliteit terug gevonden worden op de bijgevoegde cd. Deze cd-rom bevat volgende items:
De programma’s die in hoofdstuk 6 besproken werden: o Een programma voor de data van de energiemeters in de databank te zetten o Een programma voor de data van de detectiepunten in de databank te zetten o Het hoofdprogramma, bestaande uit drie delen, die achter combinaties tussen een energiemeter en één of meerdere treinritten zoekt De twee voorgaande versies van het hoofdprogramma die in hoofdstuk 7 kort besproken werden Een Excel-bestand die de grafieken van de resonantiefrequenties in hoofdstuk 4 genereerden Een Excel-bestand dat de sigma-delta ADC simuleert Een digitale versie van deze thesis
181
Bijlage 2: Engelse bespreking Op vraag van Bart Van der Spiegel, mijn promotor bij Infrabel, wordt er een korte Engelse bespreking van de programma’s van deze thesis in deze bijlage neergeschreven. Deze tekst is voor de Noorse medewerkers van Erex geschreven, aangezien zij de Nederlandse taal niet beheersen.
Small discussion of the programs written in this thesis One of the first problems that occured when the programs of this thesis was written, is that the laptop that was used didn’t possess enough memory to process all of the tms data. This started when the data from the energy meters and the tms data was transferred into a self made database. This database was created because the databases of Infrabel and Erex were not accessible. When the data of the energy meters was being transferred, no errors occurred. When the tms data was being transferred however, a memory error was displayed. For this reason the tms data was being transferred in shifts. The ArrayLists that were used for this purpose were filled at the beginning of a shift and emptied at the end of a shift. Once the lists were empty again at the end of one shift, another shift could start with the next set of tms data. Because Erex already possesses a database with the data from the energy meters and the tms data, these two programs that transfer the data (one program for the metered data and one program for the tms data) are of no use to Erex. When a first version of the main program ran, it took more than nine hours. The main program searches for combinations between non allocated energy meters and possible train rides (based on their position and time). The program uses the tms data and the data from the meters stored in the database for this process. This program saved the data from the energy meters from the database in ArrayLists and compared it with the tms data. This tms data was obtained from the database through a SQL command in Java. Because the duration of the first version was too long, a second version was written. The SQL command was now modified. A where clause was added that limited the tms data chosen from the database. After running this version however, a same time use was obtained (more than nine hours). It appears that storing data from the database once in ArrayLists for further processing takes less time than constantly asking singular data from the database through a SQL command. Of course there was still the memory issue. For this reason the tms data was added in ArrayLists but once again in shifts. The data from the meters was now being compared to the tms data and both types of data were stored in ArrayLists. After all the data of a meter was compared to a selection of the tms data (this selection changes every shift until all the tms data has been compared), a new shift could start.
182
This third and final version of the main program has a duration of two hours and fourty minutes for the 25th of Septembre 2013. This day had four unallocated energy meters. A meter with sixty elements has a processing time of seventeen minutes. Because a laptop of five years old was used, this running time can be shortened with a modern high speed computer. With such a computer the complete collection of the tms data could for example be stored in the ArrayLists without the need of using shifts thus reducing the running time.
183