Configuratie FEWS

De configuratie van FEWS bestaat uit een groot aantal xml bestanden waarvan sommige duizenden regels lang. Het onderhouden van de configuratie is een ingewikkelde klus:

  1. Default waarden moeten voor alle elementen van het systeem voortdurend herhaald worden. Erg omslachtig (veel tikwerk), maar vooral lastig te herkennen waar zich bijzondere situaties voordoen (unieke waarden).
  2. Elementen zijn onderling met elkaar gelinkt zowel binnen één xml file als tussen xml files. Het is erg ingewikkeld om deze links met de hand op de juiste manier te configureren. Een tikfout is snel gemaakt en het is lastig terug te vinden waar de fout precies zit.

Groovyfews

We zoeken daarom een manier om de configuratie te vereenvoudigen met toepassing van het DRY principe (don't repeat yourself). Gelukkig bestaan er meer mensen op zoek naar een betere aanpak. Zo heeft Flowmatters in Australie een configuratietool gemaakt mbv de (op java gebaseerde) taal Groovy: Groovyfews. Groovyfews maakt gebruik van zogenaamde helper files en biedt ondermeer een oplossing om default waarden in helper files onder te brengen. Hier maken we graag gebruik van. Om gebruik te kunnen maken van de tool van flowmatters moet je groovy (Bron) en groovyfews (Bron) geinstalleerd hebben.

Converteer FEWS naar Groovyfews

Om een bestaande FEWS configuratie om te zetten naar groovyfews hebben we een python script geschreven. Het script analyseert de aangeboden xml file op defaultwaarden en genereert een nieuwe groovyfews configuratie waarin de default waarden zijn opgeborgen in een helper file. In het formulier rechtsboven kan je een FEWS xml file aanbieden en krijg je een zip bestand met 1. groovy config file en 2. groovy helper file terug.

Voorbeeld

Input: FEWS xml config


<filters>

	<defaultFilterId>HHNK_ALL</defaultFilterId>
	<timeSeriesSets id="nkgem_ruw">
		<timeSeriesSet>
			<moduleInstanceId>ImportIREAL</moduleInstanceId>
			<valueType>scalar</valueType>
			<parameterId>H.berekend</parameterId>
			<locationSetId>NKGem_waterstand</locationSetId>
			<timeSeriesType>external historical</timeSeriesType>
			<timeStep unit="minute" multiplier="3"/>
			<relativeViewPeriod unit="day" start="-14" end="0"/>
			<readWriteMode>read only</readWriteMode>
			<synchLevel>1</synchLevel>
		</timeSeriesSet>
		<timeSeriesSet>
			<moduleInstanceId>ImportIREAL</moduleInstanceId>
			<valueType>scalar</valueType>
			<parameterId>H.niveau</parameterId>
			<locationSetId>NKGem_niveau</locationSetId>
			<timeSeriesType>external historical</timeSeriesType>
			<timeStep unit="minute" multiplier="3"/>
			<relativeViewPeriod unit="day" start="-14" end="0"/>
			<readWriteMode>read only</readWriteMode>
			<synchLevel>1</synchLevel>
		</timeSeriesSet>
		<timeSeriesSet>
			<moduleInstanceId>ImportIREAL</moduleInstanceId>
			<valueType>scalar</valueType>
			<parameterId>H.niveau.dag</parameterId>
			<locationSetId>NKGem_niveau_dag</locationSetId>
			<timeSeriesType>external historical</timeSeriesType>
			<timeStep unit="nonequidistant"/>
			<relativeViewPeriod unit="day" start="-14" end="0"/>
			<readWriteMode>read only</readWriteMode>
			<synchLevel>1</synchLevel>
		</timeSeriesSet>
		<timeSeriesSet>
			<moduleInstanceId>ImportIREAL</moduleInstanceId>
			<valueType>scalar</valueType>
			<parameterId>P.meting</parameterId>
			<locationSetId>NKGem_neerslag</locationSetId>
			<timeSeriesType>external historical</timeSeriesType>
			<timeStep unit="minute" multiplier="3"/>
			<relativeViewPeriod unit="day" start="-14" end="0"/>
			<readWriteMode>read only</readWriteMode>
			<synchLevel>1</synchLevel>
		</timeSeriesSet>
	</timeSeriesSets>
	<timeSeriesSets id="nkgem_prod">
		<timeSeriesSet>
			<moduleInstanceId>Productie</moduleInstanceId>
			<valueType>scalar</valueType>
			<parameterId>H.berekend</parameterId>
			<locationSetId>NKGem_waterstand</locationSetId>
			<timeSeriesType>external historical</timeSeriesType>
			<timeStep unit="minute" multiplier="3"/>
			<relativeViewPeriod unit="day" start="-14" end="0"/>
			<readWriteMode>editing visible to all future task runs</readWriteMode>
			<synchLevel>5</synchLevel>
		</timeSeriesSet>
		<timeSeriesSet>
			<moduleInstanceId>Productie</moduleInstanceId>
			<valueType>scalar</valueType>
			<parameterId>H.niveau</parameterId>
			<locationSetId>NKGem_niveau</locationSetId>
			<timeSeriesType>external historical</timeSeriesType>
			<timeStep unit="minute" multiplier="3"/>
			<relativeViewPeriod unit="day" start="-14" end="0"/>
			<readWriteMode>editing visible to all future task runs</readWriteMode>
			<synchLevel>5</synchLevel>
		</timeSeriesSet>
	</timeSeriesSets>
	<filter id="HHNK_Mobiel" name="Mobiele metingen">
		<timeSeriesSet>
			<moduleInstanceId>Productie</moduleInstanceId>
			<valueType>scalar</valueType>
			<parameterId>O2.meting</parameterId>
			<locationSetId>Mobiel_MP_Zuurstof</locationSetId>
			<timeSeriesType>external historical</timeSeriesType>
			<timeStep unit="nonequidistant"/>
			<relativeViewPeriod unit="day" start="-30" end="0"/>
			<readWriteMode>editing visible to all future task runs</readWriteMode>
			<synchLevel>5</synchLevel>
		</timeSeriesSet>
		<timeSeriesSet>
			<moduleInstanceId>Productie</moduleInstanceId>
			<valueType>scalar</valueType>
			<parameterId>EGV.meting</parameterId>
			<locationSetId>Mobiel_MP_EGV</locationSetId>
			<timeSeriesType>external historical</timeSeriesType>
			<timeStep unit="nonequidistant"/>
			<relativeViewPeriod unit="day" start="-30" end="0"/>
			<readWriteMode>editing visible to all future task runs</readWriteMode>
			<synchLevel>5</synchLevel>
		</timeSeriesSet>
	</filter>

</filters>

Output: Groovyfews config file


filters('') {

	defaultFilterId('HHNK_ALL')
	timeSeriesSets(id:'nkgem_ruw') {
		__Filters_test.tss_nkgem_ruw(
			parameterId:'H.berekend',
			locationSetId:'NKGem_waterstand',
			delegate
		)
		__Filters_test.tss_nkgem_ruw(
			parameterId:'H.niveau',
			locationSetId:'NKGem_niveau',
			delegate
		)
		__Filters_test.tss_nkgem_ruw(
			parameterId:'H.niveau.dag',
			locationSetId:'NKGem_niveau_dag',
			timeStep:['unit': 'nonequidistant'],
			delegate
		)
		__Filters_test.tss_nkgem_ruw(
			parameterId:'P.meting',
			locationSetId:'NKGem_neerslag',
			delegate
		)
	}
	timeSeriesSets(id:'nkgem_prod') {
		__Filters_test.tss_nkgem_prod(
			parameterId:'H.berekend',
			locationSetId:'NKGem_waterstand',
			delegate
		)
		__Filters_test.tss_nkgem_prod(
			parameterId:'H.niveau',
			locationSetId:'NKGem_niveau',
			delegate
		)
	}
	filter('id': 'HHNK_Mobiel', 'name': 'Mobiele metingen') {
		__Filters_test.tss_None(
			parameterId:'O2.meting',
			locationSetId:'Mobiel_MP_Zuurstof',
			delegate
		)
		__Filters_test.tss_None(
			parameterId:'EGV.meting',
			locationSetId:'Mobiel_MP_EGV',
			delegate
		)
	}

} }

Output: Groovy Helper file


static def tss_default(Map map,d) {

	def defaults= [
		'synchLevel':'NonDefault'
		,'locationSetId':'NonDefault'
		,'timeStep':['unit': 'minute', 'multiplier': '3']
		,'valueType':'scalar'
		,'parameterId':'NonDefault'
		,'relativeViewPeriod':['start': '-14', 'end': '0', 'unit': 'day']
		,'readWriteMode':'NonDefault'
		,'moduleInstanceId':'NonDefault'
		,'timeSeriesType':'external historical'
	]
	def params = defaults + map
	d.timeSeriesSet() { ['synchLevel','locationSetId','timeStep','valueType','parameterId',			'relativeViewPeriod','readWriteMode','moduleInstanceId','timeSeriesType'].each 
			{ k -> "$k"(params[k])
		}
	}

}

static def tss_nkgem_ruw(Map map,d) {

	def nkgem_ruw_params = [
		'synchLevel':'1'
		,'readWriteMode':'read only'
		,'moduleInstanceId':'ImportIREAL'
	]
	tss_default(nkgem_ruw_params + map,d)

}

static def tss_nkgem_prod(Map map,d) {

	def nkgem_prod_params = [
		'synchLevel':'5'
		,'readWriteMode':'editing visible to all future task runs'
		,'moduleInstanceId':'Productie'
	]
	tss_default(nkgem_prod_params + map,d)

}

static def tss_None(Map map,d) {

	def None_params = [
		'synchLevel':'5'
		,'timeStep':['unit': 'nonequidistant']
		,'relativeViewPeriod':['start': '-30', 'end': '0', 'unit': 'day']
		,'readWriteMode':'editing visible to all future task runs'
		,'moduleInstanceId':'Productie'
	]
	tss_default(None_params + map,d)

}

Logboek

April 2014. versie1

versie 1 van xml2gfews gemaakt. Test uitgevoerd op een bestaande FEWS config xml file (Filters.xml) van 4000 regels lang.

 1. FEWS xml door xml2GFEWS gehaald. Output: Filters.groovy en __Filters.groovy
 2. Output uit 1 door groovyfews gehaald. Output: FEWS xml (Filters.xml)
 3. input FEWS xml en output uit 2. met elkaar vergeleken. Beide bestanden zijn identiek met uitzondering van:
   * begin tabs zijn dubbele spaties geworden. Is denk ik geen probleem, maar moet gechecked worden
   * de volgorde van de elementen is veranderd. Is denk ik geen probleem, maar moet gechecked worden
   * de output heeft zo'n 30 elementen meer dan de input. Alle betreffende elementen zijn elementen die waarschijnlijk abusievelijk in de input zijn weggelaten en door groovyfews alsnog zijn geplaatst in de output.

Nieuws

  • mei 2018, Thematische kaarten aangepast (figuur met aantallen metingen per periode toegevoegd).
  • november 2017, Meetnetten aangepast, meetnetten opgenomen in download meetpunten
  • maart 2017, Imwa meetwaarden gereedschap toegevoegd in de rubriek Gereedschappen
  • maart 2017, Meetpunten atlas bijgewerkt (Watertypen versie 2016 toegevoegd)
  • december 2016, Stoffen tov MAC-MKN, hoe vaak zijn stoffen gemeten, hoe vaak en hoeveel boven de MAC-waarde enz.
  • september 2016, Directe download meetresultaten als GeoJson of CSV toegevoegd in de rubriek Gereedschappen.
  • januari 2016, Bladzijde KRW geeft toegang tot diverse KRW rapportages en factsheets
  • december 2015, Demo voor een Dataportaal HPZ en demo voor Dijkprofielen gemaakt.
  • oktober 2015, Het hoofdrapport van de studie naar de achtergrondbelasting van het oppervlaktewater met stikstof en fosfor is toegevoegd.
  • september 2015, Thematische kaarten aangepast (nieuwe achtergrond toegevoegd voor betere leesbaarheid, start nu op met de periode 2010-2014 met kleurschema rood) De schalen zijn aangepast zodat meer details zichtbaar worden.
  • september 2015, Statistiek per gebied heeft nu ook data van zwevend stof.
  • september 2015, Meetpunten atlas, kies een meetpunt en er komt een bladzijde met luchtfoto's, foto's, chloride en sulfaatgehaltes, huidig KRW type en overige achtergrondinfo.
  • mei 2015, Signalen Datawatt voor 2011, een bladzijde om historische reeksen meetdata van gemalen die geregistreerd zijn met de oude datawatt / tmx apparatuur op te halen.
  • Oudernieuws