Initial commit

This commit is contained in:
2018-09-22 10:26:24 +08:00
commit 58bbbaf6de
114 changed files with 9151 additions and 0 deletions

413
test/lib/example.xml Normal file
View File

@@ -0,0 +1,413 @@
<?xml version="1.0" encoding="utf-8"?>
<weatherdata>
<location>
<name>Karlsruhe</name>
<type>Administration centre</type>
<country>Germany</country>
<timezone id="Europe/Berlin" utcoffsetMinutes="120" />
<location altitude="115" latitude="49.00472" longitude="8.38583" geobase="geonames" geobaseid="2892794" />
</location>
<credit>
<!--In order to use the free weather data from yr no, you HAVE to display
the following text clearly visible on your web page. The text should be a
link to the specified URL.-->
<!--Please read more about our conditions and guidelines at http://om.yr.no/verdata/ English explanation at http://om.yr.no/verdata/free-weather-data/-->
<link text="Weather forecast from Yr, delivered by the Norwegian Meteorological Institute and the NRK" url="http://www.yr.no/place/Germany/Baden-Württemberg/Karlsruhe/" />
</credit>
<links>
<link id="xmlSource" url="http://www.yr.no/place/Germany/Baden-Württemberg/Karlsruhe/forecast.xml" />
<link id="xmlSourceHourByHour" url="http://www.yr.no/place/Germany/Baden-Württemberg/Karlsruhe/forecast_hour_by_hour.xml" />
<link id="overview" url="http://www.yr.no/place/Germany/Baden-Württemberg/Karlsruhe/" />
<link id="hourByHour" url="http://www.yr.no/place/Germany/Baden-Württemberg/Karlsruhe/hour_by_hour" />
<link id="longTermForecast" url="http://www.yr.no/place/Germany/Baden-Württemberg/Karlsruhe/long" />
</links>
<meta>
<lastupdate>2018-07-28T09:38:00</lastupdate>
<nextupdate>2018-07-28T22:00:00</nextupdate>
</meta>
<sun rise="2018-07-28T05:53:48" set="2018-07-28T21:11:17" />
<forecast>
<tabular>
<time from="2018-07-28T16:00:00" to="2018-07-28T18:00:00" period="2">
<!-- Valid from 2018-07-28T16:00:00 to 2018-07-28T18:00:00 -->
<symbol number="3" numberEx="3" name="Partly cloudy" var="03d" />
<precipitation value="0" />
<!-- Valid at 2018-07-28T16:00:00 -->
<windDirection deg="252.8" code="WSW" name="West-southwest" />
<windSpeed mps="6.2" name="Moderate breeze" />
<temperature unit="celsius" value="27" />
<pressure unit="hPa" value="1010.2" />
</time>
<time from="2018-07-28T18:00:00" to="2018-07-29T00:00:00" period="3">
<!-- Valid from 2018-07-28T18:00:00 to 2018-07-29T00:00:00 -->
<symbol number="2" numberEx="2" name="Fair" var="02d" />
<precipitation value="0" />
<!-- Valid at 2018-07-28T18:00:00 -->
<windDirection deg="238.0" code="WSW" name="West-southwest" />
<windSpeed mps="3.8" name="Gentle breeze" />
<temperature unit="celsius" value="28" />
<pressure unit="hPa" value="1010.7" />
</time>
<time from="2018-07-29T00:00:00" to="2018-07-29T06:00:00" period="0">
<!-- Valid from 2018-07-29T00:00:00 to 2018-07-29T06:00:00 -->
<symbol number="3" numberEx="3" name="Partly cloudy" var="03n" />
<precipitation value="0" />
<!-- Valid at 2018-07-29T00:00:00 -->
<windDirection deg="242.1" code="WSW" name="West-southwest" />
<windSpeed mps="2.7" name="Light breeze" />
<temperature unit="celsius" value="23" />
<pressure unit="hPa" value="1013.3" />
</time>
<time from="2018-07-29T06:00:00" to="2018-07-29T12:00:00" period="1">
<!-- Valid from 2018-07-29T06:00:00 to 2018-07-29T12:00:00 -->
<symbol number="4" numberEx="4" name="Cloudy" var="04" />
<precipitation value="0" />
<!-- Valid at 2018-07-29T06:00:00 -->
<windDirection deg="275.7" code="W" name="West" />
<windSpeed mps="0.6" name="Light air" />
<temperature unit="celsius" value="20" />
<pressure unit="hPa" value="1014.3" />
</time>
<time from="2018-07-29T12:00:00" to="2018-07-29T18:00:00" period="2">
<!-- Valid from 2018-07-29T12:00:00 to 2018-07-29T18:00:00 -->
<symbol number="3" numberEx="3" name="Partly cloudy" var="03d" />
<precipitation value="0" />
<!-- Valid at 2018-07-29T12:00:00 -->
<windDirection deg="76.6" code="ENE" name="East-northeast" />
<windSpeed mps="0.2" name="Calm" />
<temperature unit="celsius" value="28" />
<pressure unit="hPa" value="1014.3" />
</time>
<time from="2018-07-29T18:00:00" to="2018-07-30T00:00:00" period="3">
<!-- Valid from 2018-07-29T18:00:00 to 2018-07-30T00:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01d" />
<precipitation value="0" />
<!-- Valid at 2018-07-29T18:00:00 -->
<windDirection deg="228.3" code="SW" name="Southwest" />
<windSpeed mps="2.8" name="Light breeze" />
<temperature unit="celsius" value="31" />
<pressure unit="hPa" value="1012.2" />
</time>
<time from="2018-07-30T00:00:00" to="2018-07-30T06:00:00" period="0">
<!-- Valid from 2018-07-30T00:00:00 to 2018-07-30T06:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01n" />
<precipitation value="0" />
<!-- Valid at 2018-07-30T00:00:00 -->
<windDirection deg="110.7" code="ESE" name="East-southeast" />
<windSpeed mps="0.7" name="Light air" />
<temperature unit="celsius" value="23" />
<pressure unit="hPa" value="1014.1" />
</time>
<time from="2018-07-30T06:00:00" to="2018-07-30T12:00:00" period="1">
<!-- Valid from 2018-07-30T06:00:00 to 2018-07-30T12:00:00 -->
<symbol number="3" numberEx="3" name="Partly cloudy" var="03d" />
<precipitation value="0" />
<!-- Valid at 2018-07-30T06:00:00 -->
<windDirection deg="6.4" code="N" name="North" />
<windSpeed mps="0.5" name="Light air" />
<temperature unit="celsius" value="20" />
<pressure unit="hPa" value="1014.8" />
</time>
<time from="2018-07-30T12:00:00" to="2018-07-30T18:00:00" period="2">
<!-- Valid from 2018-07-30T12:00:00 to 2018-07-30T18:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01d" />
<precipitation value="0" />
<!-- Valid at 2018-07-30T12:00:00 -->
<windDirection deg="281.8" code="WNW" name="West-northwest" />
<windSpeed mps="1.0" name="Light air" />
<temperature unit="celsius" value="31" />
<pressure unit="hPa" value="1015.8" />
</time>
<time from="2018-07-30T18:00:00" to="2018-07-31T00:00:00" period="3">
<!-- Valid from 2018-07-30T18:00:00 to 2018-07-31T00:00:00 -->
<symbol number="2" numberEx="2" name="Fair" var="02d" />
<precipitation value="0" />
<!-- Valid at 2018-07-30T18:00:00 -->
<windDirection deg="203.6" code="SSW" name="South-southwest" />
<windSpeed mps="2.1" name="Light breeze" />
<temperature unit="celsius" value="34" />
<pressure unit="hPa" value="1013.3" />
</time>
<time from="2018-07-31T00:00:00" to="2018-07-31T06:00:00" period="0">
<!-- Valid from 2018-07-31T00:00:00 to 2018-07-31T06:00:00 -->
<symbol number="2" numberEx="2" name="Fair" var="02n" />
<precipitation value="0" />
<!-- Valid at 2018-07-31T00:00:00 -->
<windDirection deg="336.3" code="NNW" name="North-northwest" />
<windSpeed mps="2.3" name="Light breeze" />
<temperature unit="celsius" value="26" />
<pressure unit="hPa" value="1015.6" />
</time>
<time from="2018-07-31T08:00:00" to="2018-07-31T14:00:00" period="1">
<!-- Valid from 2018-07-31T08:00:00 to 2018-07-31T14:00:00 -->
<symbol number="2" numberEx="2" name="Fair" var="02d" />
<precipitation value="0" />
<!-- Valid at 2018-07-31T08:00:00 -->
<windDirection deg="61.9" code="ENE" name="East-northeast" />
<windSpeed mps="0.7" name="Light air" />
<temperature unit="celsius" value="25" />
<pressure unit="hPa" value="1016.4" />
</time>
<time from="2018-07-31T14:00:00" to="2018-07-31T20:00:00" period="2">
<!-- Valid from 2018-07-31T14:00:00 to 2018-07-31T20:00:00 -->
<symbol number="3" numberEx="3" name="Partly cloudy" var="03d" />
<precipitation value="0" />
<!-- Valid at 2018-07-31T14:00:00 -->
<windDirection deg="329.5" code="NNW" name="North-northwest" />
<windSpeed mps="1.8" name="Light breeze" />
<temperature unit="celsius" value="34" />
<pressure unit="hPa" value="1015.6" />
</time>
<time from="2018-07-31T20:00:00" to="2018-08-01T02:00:00" period="3">
<!-- Valid from 2018-07-31T20:00:00 to 2018-08-01T02:00:00 -->
<symbol number="2" numberEx="2" name="Fair" var="02d" />
<precipitation value="0" />
<!-- Valid at 2018-07-31T20:00:00 -->
<windDirection deg="279.4" code="W" name="West" />
<windSpeed mps="2.2" name="Light breeze" />
<temperature unit="celsius" value="32" />
<pressure unit="hPa" value="1015.1" />
</time>
<time from="2018-08-01T02:00:00" to="2018-08-01T08:00:00" period="0">
<!-- Valid from 2018-08-01T02:00:00 to 2018-08-01T08:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01n" />
<precipitation value="0" />
<!-- Valid at 2018-08-01T02:00:00 -->
<windDirection deg="25.5" code="NNE" name="North-northeast" />
<windSpeed mps="2.1" name="Light breeze" />
<temperature unit="celsius" value="25" />
<pressure unit="hPa" value="1016.7" />
</time>
<time from="2018-08-01T08:00:00" to="2018-08-01T14:00:00" period="1">
<!-- Valid from 2018-08-01T08:00:00 to 2018-08-01T14:00:00 -->
<symbol number="2" numberEx="2" name="Fair" var="02d" />
<precipitation value="0" />
<!-- Valid at 2018-08-01T08:00:00 -->
<windDirection deg="13.6" code="NNE" name="North-northeast" />
<windSpeed mps="1.8" name="Light breeze" />
<temperature unit="celsius" value="25" />
<pressure unit="hPa" value="1016.8" />
</time>
<time from="2018-08-01T14:00:00" to="2018-08-01T20:00:00" period="2">
<!-- Valid from 2018-08-01T14:00:00 to 2018-08-01T20:00:00 -->
<symbol number="3" numberEx="3" name="Partly cloudy" var="03d" />
<precipitation value="0" />
<!-- Valid at 2018-08-01T14:00:00 -->
<windDirection deg="17.3" code="NNE" name="North-northeast" />
<windSpeed mps="1.6" name="Light breeze" />
<temperature unit="celsius" value="35" />
<pressure unit="hPa" value="1015.7" />
</time>
<time from="2018-08-01T20:00:00" to="2018-08-02T02:00:00" period="3">
<!-- Valid from 2018-08-01T20:00:00 to 2018-08-02T02:00:00 -->
<symbol number="4" numberEx="4" name="Cloudy" var="04" />
<precipitation value="0" />
<!-- Valid at 2018-08-01T20:00:00 -->
<windDirection deg="345.4" code="NNW" name="North-northwest" />
<windSpeed mps="1.9" name="Light breeze" />
<temperature unit="celsius" value="31" />
<pressure unit="hPa" value="1016.5" />
</time>
<time from="2018-08-02T02:00:00" to="2018-08-02T08:00:00" period="0">
<!-- Valid from 2018-08-02T02:00:00 to 2018-08-02T08:00:00 -->
<symbol number="2" numberEx="2" name="Fair" var="02n" />
<precipitation value="0" />
<!-- Valid at 2018-08-02T02:00:00 -->
<windDirection deg="351.9" code="N" name="North" />
<windSpeed mps="1.2" name="Light air" />
<temperature unit="celsius" value="23" />
<pressure unit="hPa" value="1019.9" />
</time>
<time from="2018-08-02T08:00:00" to="2018-08-02T14:00:00" period="1">
<!-- Valid from 2018-08-02T08:00:00 to 2018-08-02T14:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01d" />
<precipitation value="0" />
<!-- Valid at 2018-08-02T08:00:00 -->
<windDirection deg="357.2" code="N" name="North" />
<windSpeed mps="1.5" name="Light air" />
<temperature unit="celsius" value="23" />
<pressure unit="hPa" value="1021.1" />
</time>
<time from="2018-08-02T14:00:00" to="2018-08-02T20:00:00" period="2">
<!-- Valid from 2018-08-02T14:00:00 to 2018-08-02T20:00:00 -->
<symbol number="2" numberEx="2" name="Fair" var="02d" />
<precipitation value="0" />
<!-- Valid at 2018-08-02T14:00:00 -->
<windDirection deg="2.8" code="N" name="North" />
<windSpeed mps="2.3" name="Light breeze" />
<temperature unit="celsius" value="30" />
<pressure unit="hPa" value="1020.1" />
</time>
<time from="2018-08-02T20:00:00" to="2018-08-03T02:00:00" period="3">
<!-- Valid from 2018-08-02T20:00:00 to 2018-08-03T02:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01d" />
<precipitation value="0" />
<!-- Valid at 2018-08-02T20:00:00 -->
<windDirection deg="11.6" code="NNE" name="North-northeast" />
<windSpeed mps="2.0" name="Light breeze" />
<temperature unit="celsius" value="29" />
<pressure unit="hPa" value="1019.6" />
</time>
<time from="2018-08-03T02:00:00" to="2018-08-03T08:00:00" period="0">
<!-- Valid from 2018-08-03T02:00:00 to 2018-08-03T08:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01n" />
<precipitation value="0" />
<!-- Valid at 2018-08-03T02:00:00 -->
<windDirection deg="16.3" code="NNE" name="North-northeast" />
<windSpeed mps="3.2" name="Light breeze" />
<temperature unit="celsius" value="24" />
<pressure unit="hPa" value="1021.0" />
</time>
<time from="2018-08-03T08:00:00" to="2018-08-03T14:00:00" period="1">
<!-- Valid from 2018-08-03T08:00:00 to 2018-08-03T14:00:00 -->
<symbol number="2" numberEx="2" name="Fair" var="02d" />
<precipitation value="0" />
<!-- Valid at 2018-08-03T08:00:00 -->
<windDirection deg="18.1" code="NNE" name="North-northeast" />
<windSpeed mps="2.6" name="Light breeze" />
<temperature unit="celsius" value="23" />
<pressure unit="hPa" value="1021.9" />
</time>
<time from="2018-08-03T14:00:00" to="2018-08-03T20:00:00" period="2">
<!-- Valid from 2018-08-03T14:00:00 to 2018-08-03T20:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01d" />
<precipitation value="0" />
<!-- Valid at 2018-08-03T14:00:00 -->
<windDirection deg="24.2" code="NNE" name="North-northeast" />
<windSpeed mps="2.4" name="Light breeze" />
<temperature unit="celsius" value="31" />
<pressure unit="hPa" value="1020.0" />
</time>
<time from="2018-08-03T20:00:00" to="2018-08-04T02:00:00" period="3">
<!-- Valid from 2018-08-03T20:00:00 to 2018-08-04T02:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01d" />
<precipitation value="0" />
<!-- Valid at 2018-08-03T20:00:00 -->
<windDirection deg="1.9" code="N" name="North" />
<windSpeed mps="3.2" name="Light breeze" />
<temperature unit="celsius" value="31" />
<pressure unit="hPa" value="1018.6" />
</time>
<time from="2018-08-04T02:00:00" to="2018-08-04T08:00:00" period="0">
<!-- Valid from 2018-08-04T02:00:00 to 2018-08-04T08:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01n" />
<precipitation value="0" />
<!-- Valid at 2018-08-04T02:00:00 -->
<windDirection deg="40.2" code="NE" name="Northeast" />
<windSpeed mps="2.0" name="Light breeze" />
<temperature unit="celsius" value="22" />
<pressure unit="hPa" value="1020.2" />
</time>
<time from="2018-08-04T08:00:00" to="2018-08-04T14:00:00" period="1">
<!-- Valid from 2018-08-04T08:00:00 to 2018-08-04T14:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01d" />
<precipitation value="0" />
<!-- Valid at 2018-08-04T08:00:00 -->
<windDirection deg="47.2" code="NE" name="Northeast" />
<windSpeed mps="2.9" name="Light breeze" />
<temperature unit="celsius" value="22" />
<pressure unit="hPa" value="1020.6" />
</time>
<time from="2018-08-04T14:00:00" to="2018-08-04T20:00:00" period="2">
<!-- Valid from 2018-08-04T14:00:00 to 2018-08-04T20:00:00 -->
<symbol number="2" numberEx="2" name="Fair" var="02d" />
<precipitation value="0" />
<!-- Valid at 2018-08-04T14:00:00 -->
<windDirection deg="52.2" code="NE" name="Northeast" />
<windSpeed mps="3.3" name="Light breeze" />
<temperature unit="celsius" value="32" />
<pressure unit="hPa" value="1018.5" />
</time>
<time from="2018-08-04T20:00:00" to="2018-08-05T02:00:00" period="3">
<!-- Valid from 2018-08-04T20:00:00 to 2018-08-05T02:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01d" />
<precipitation value="0" />
<!-- Valid at 2018-08-04T20:00:00 -->
<windDirection deg="74.2" code="ENE" name="East-northeast" />
<windSpeed mps="2.7" name="Light breeze" />
<temperature unit="celsius" value="31" />
<pressure unit="hPa" value="1017.0" />
</time>
<time from="2018-08-05T02:00:00" to="2018-08-05T08:00:00" period="0">
<!-- Valid from 2018-08-05T02:00:00 to 2018-08-05T08:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01n" />
<precipitation value="0" />
<!-- Valid at 2018-08-05T02:00:00 -->
<windDirection deg="74.9" code="ENE" name="East-northeast" />
<windSpeed mps="1.7" name="Light breeze" />
<temperature unit="celsius" value="23" />
<pressure unit="hPa" value="1017.7" />
</time>
<time from="2018-08-05T08:00:00" to="2018-08-05T14:00:00" period="1">
<!-- Valid from 2018-08-05T08:00:00 to 2018-08-05T14:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01d" />
<precipitation value="0" />
<!-- Valid at 2018-08-05T08:00:00 -->
<windDirection deg="56.6" code="ENE" name="East-northeast" />
<windSpeed mps="2.7" name="Light breeze" />
<temperature unit="celsius" value="23" />
<pressure unit="hPa" value="1018.3" />
</time>
<time from="2018-08-05T14:00:00" to="2018-08-05T20:00:00" period="2">
<!-- Valid from 2018-08-05T14:00:00 to 2018-08-05T20:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01d" />
<precipitation value="0" />
<!-- Valid at 2018-08-05T14:00:00 -->
<windDirection deg="93.2" code="E" name="East" />
<windSpeed mps="3.3" name="Light breeze" />
<temperature unit="celsius" value="34" />
<pressure unit="hPa" value="1016.8" />
</time>
<time from="2018-08-05T20:00:00" to="2018-08-06T02:00:00" period="3">
<!-- Valid from 2018-08-05T20:00:00 to 2018-08-06T02:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01n" />
<precipitation value="0" />
<!-- Valid at 2018-08-05T20:00:00 -->
<windDirection deg="119.6" code="ESE" name="East-southeast" />
<windSpeed mps="1.6" name="Light breeze" />
<temperature unit="celsius" value="32" />
<pressure unit="hPa" value="1015.0" />
</time>
<time from="2018-08-06T02:00:00" to="2018-08-06T08:00:00" period="0">
<!-- Valid from 2018-08-06T02:00:00 to 2018-08-06T08:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01n" />
<precipitation value="0" />
<!-- Valid at 2018-08-06T02:00:00 -->
<windDirection deg="133.9" code="SE" name="Southeast" />
<windSpeed mps="1.8" name="Light breeze" />
<temperature unit="celsius" value="25" />
<pressure unit="hPa" value="1015.7" />
</time>
<time from="2018-08-06T08:00:00" to="2018-08-06T14:00:00" period="1">
<!-- Valid from 2018-08-06T08:00:00 to 2018-08-06T14:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01d" />
<precipitation value="0" />
<!-- Valid at 2018-08-06T08:00:00 -->
<windDirection deg="242.1" code="WSW" name="West-southwest" />
<windSpeed mps="0.9" name="Light air" />
<temperature unit="celsius" value="25" />
<pressure unit="hPa" value="1016.8" />
</time>
<time from="2018-08-06T14:00:00" to="2018-08-06T20:00:00" period="2">
<!-- Valid from 2018-08-06T14:00:00 to 2018-08-06T20:00:00 -->
<symbol number="3" numberEx="3" name="Partly cloudy" var="03d" />
<precipitation value="0" />
<!-- Valid at 2018-08-06T14:00:00 -->
<windDirection deg="254.2" code="WSW" name="West-southwest" />
<windSpeed mps="1.9" name="Light breeze" />
<temperature unit="celsius" value="37" />
<pressure unit="hPa" value="1015.3" />
</time>
<time from="2018-08-06T20:00:00" to="2018-08-07T02:00:00" period="3">
<!-- Valid from 2018-08-06T20:00:00 to 2018-08-07T02:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01n" />
<precipitation value="0" />
<!-- Valid at 2018-08-06T20:00:00 -->
<windDirection deg="196.8" code="SSW" name="South-southwest" />
<windSpeed mps="1.7" name="Light breeze" />
<temperature unit="celsius" value="33" />
<pressure unit="hPa" value="1013.1" />
</time>
</tabular>
</forecast>
</weatherdata>

413
test/lib/forecast.xml Normal file
View File

@@ -0,0 +1,413 @@
<?xml version="1.0" encoding="utf-8"?>
<weatherdata>
<location>
<name>Stuttgart</name>
<type>Regional capital</type>
<country>Germany</country>
<timezone id="Europe/Berlin" utcoffsetMinutes="60" />
<location altitude="252" latitude="48.78232" longitude="9.17702" geobase="geonames" geobaseid="2825297" />
</location>
<credit>
<!--In order to use the free weather data from yr no, you HAVE to display
the following text clearly visible on your web page. The text should be a
link to the specified URL.-->
<!--Please read more about our conditions and guidelines at http://om.yr.no/verdata/ English explanation at http://om.yr.no/verdata/free-weather-data/-->
<link text="Weather forecast from yr.no, delivered by the Norwegian Meteorological Institute and the NRK" url="http://www.yr.no/place/Germany/Baden-Württemberg/Stuttgart/" />
</credit>
<links>
<link id="xmlSource" url="http://www.yr.no/place/Germany/Baden-Württemberg/Stuttgart/forecast.xml" />
<link id="xmlSourceHourByHour" url="http://www.yr.no/place/Germany/Baden-Württemberg/Stuttgart/forecast_hour_by_hour.xml" />
<link id="overview" url="http://www.yr.no/place/Germany/Baden-Württemberg/Stuttgart/" />
<link id="hourByHour" url="http://www.yr.no/place/Germany/Baden-Württemberg/Stuttgart/hour_by_hour" />
<link id="longTermForecast" url="http://www.yr.no/place/Germany/Baden-Württemberg/Stuttgart/long" />
</links>
<meta>
<lastupdate>2016-03-15T04:39:00</lastupdate>
<nextupdate>2016-03-15T17:00:00</nextupdate>
</meta>
<sun rise="2016-03-15T06:36:05" set="2016-03-15T18:29:00" />
<forecast>
<tabular>
<time from="2016-03-15T16:00:00" to="2016-03-15T18:00:00" period="2">
<!-- Valid from 2016-03-15T16:00:00 to 2016-03-15T18:00:00 -->
<symbol number="4" numberEx="4" name="Cloudy" var="04" />
<precipitation value="0" minvalue="0" maxvalue="0.1" />
<!-- Valid at 2016-03-15T16:00:00 -->
<windDirection deg="19.2" code="NNE" name="North-northeast" />
<windSpeed mps="2.7" name="Light breeze" />
<temperature unit="celsius" value="3" />
<pressure unit="hPa" value="1021.9" />
</time>
<time from="2016-03-15T18:00:00" to="2016-03-16T00:00:00" period="3">
<!-- Valid from 2016-03-15T18:00:00 to 2016-03-16T00:00:00 -->
<symbol number="3" numberEx="3" name="Partly cloudy" var="mf/03n.22" />
<precipitation value="0" minvalue="0" maxvalue="0.1" />
<!-- Valid at 2016-03-15T18:00:00 -->
<windDirection deg="41.9" code="NE" name="Northeast" />
<windSpeed mps="3.4" name="Gentle breeze" />
<temperature unit="celsius" value="3" />
<pressure unit="hPa" value="1022.3" />
</time>
<time from="2016-03-16T00:00:00" to="2016-03-16T06:00:00" period="0">
<!-- Valid from 2016-03-16T00:00:00 to 2016-03-16T06:00:00 -->
<symbol number="3" numberEx="3" name="Partly cloudy" var="mf/03n.25" />
<precipitation value="0" />
<!-- Valid at 2016-03-16T00:00:00 -->
<windDirection deg="47.9" code="NE" name="Northeast" />
<windSpeed mps="3.1" name="Light breeze" />
<temperature unit="celsius" value="1" />
<pressure unit="hPa" value="1023.2" />
</time>
<time from="2016-03-16T06:00:00" to="2016-03-16T12:00:00" period="1">
<!-- Valid from 2016-03-16T06:00:00 to 2016-03-16T12:00:00 -->
<symbol number="2" numberEx="2" name="Fair" var="02d" />
<precipitation value="0" minvalue="0" maxvalue="0.1" />
<!-- Valid at 2016-03-16T06:00:00 -->
<windDirection deg="61.1" code="ENE" name="East-northeast" />
<windSpeed mps="4.0" name="Gentle breeze" />
<temperature unit="celsius" value="0" />
<pressure unit="hPa" value="1023.1" />
</time>
<time from="2016-03-16T12:00:00" to="2016-03-16T18:00:00" period="2">
<!-- Valid from 2016-03-16T12:00:00 to 2016-03-16T18:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01d" />
<precipitation value="0" />
<!-- Valid at 2016-03-16T12:00:00 -->
<windDirection deg="81.8" code="E" name="East" />
<windSpeed mps="7.3" name="Moderate breeze" />
<temperature unit="celsius" value="7" />
<pressure unit="hPa" value="1022.5" />
</time>
<time from="2016-03-16T18:00:00" to="2016-03-17T00:00:00" period="3">
<!-- Valid from 2016-03-16T18:00:00 to 2016-03-17T00:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="mf/01n.25" />
<precipitation value="0" />
<!-- Valid at 2016-03-16T18:00:00 -->
<windDirection deg="81.7" code="E" name="East" />
<windSpeed mps="5.5" name="Moderate breeze" />
<temperature unit="celsius" value="7" />
<pressure unit="hPa" value="1023.3" />
</time>
<time from="2016-03-17T00:00:00" to="2016-03-17T06:00:00" period="0">
<!-- Valid from 2016-03-17T00:00:00 to 2016-03-17T06:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="mf/01n.29" />
<precipitation value="0" />
<!-- Valid at 2016-03-17T00:00:00 -->
<windDirection deg="75.2" code="ENE" name="East-northeast" />
<windSpeed mps="2.8" name="Light breeze" />
<temperature unit="celsius" value="0" />
<pressure unit="hPa" value="1026.6" />
</time>
<time from="2016-03-17T06:00:00" to="2016-03-17T12:00:00" period="1">
<!-- Valid from 2016-03-17T06:00:00 to 2016-03-17T12:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01d" />
<precipitation value="0" />
<!-- Valid at 2016-03-17T06:00:00 -->
<windDirection deg="75.3" code="ENE" name="East-northeast" />
<windSpeed mps="1.8" name="Light breeze" />
<temperature unit="celsius" value="-3" />
<pressure unit="hPa" value="1026.3" />
</time>
<time from="2016-03-17T12:00:00" to="2016-03-17T18:00:00" period="2">
<!-- Valid from 2016-03-17T12:00:00 to 2016-03-17T18:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01d" />
<precipitation value="0" />
<!-- Valid at 2016-03-17T12:00:00 -->
<windDirection deg="50.6" code="NE" name="Northeast" />
<windSpeed mps="2.0" name="Light breeze" />
<temperature unit="celsius" value="8" />
<pressure unit="hPa" value="1024.2" />
</time>
<time from="2016-03-17T19:00:00" to="2016-03-18T01:00:00" period="3">
<!-- Valid from 2016-03-17T19:00:00 to 2016-03-18T01:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="mf/01n.29" />
<precipitation value="0" />
<!-- Valid at 2016-03-17T19:00:00 -->
<windDirection deg="19.6" code="NNE" name="North-northeast" />
<windSpeed mps="1.9" name="Light breeze" />
<temperature unit="celsius" value="7" />
<pressure unit="hPa" value="1023.0" />
</time>
<time from="2016-03-18T01:00:00" to="2016-03-18T07:00:00" period="0">
<!-- Valid from 2016-03-18T01:00:00 to 2016-03-18T07:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="mf/01n.32" />
<precipitation value="0" />
<!-- Valid at 2016-03-18T01:00:00 -->
<windDirection deg="272.9" code="W" name="West" />
<windSpeed mps="0.7" name="Light air" />
<temperature unit="celsius" value="3" />
<pressure unit="hPa" value="1022.5" />
</time>
<time from="2016-03-18T07:00:00" to="2016-03-18T13:00:00" period="1">
<!-- Valid from 2016-03-18T07:00:00 to 2016-03-18T13:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01d" />
<precipitation value="0" />
<!-- Valid at 2016-03-18T07:00:00 -->
<windDirection deg="251.0" code="WSW" name="West-southwest" />
<windSpeed mps="2.1" name="Light breeze" />
<temperature unit="celsius" value="0" />
<pressure unit="hPa" value="1020.9" />
</time>
<time from="2016-03-18T13:00:00" to="2016-03-18T19:00:00" period="2">
<!-- Valid from 2016-03-18T13:00:00 to 2016-03-18T19:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01d" />
<precipitation value="0" />
<!-- Valid at 2016-03-18T13:00:00 -->
<windDirection deg="312.1" code="NW" name="Northwest" />
<windSpeed mps="2.0" name="Light breeze" />
<temperature unit="celsius" value="11" />
<pressure unit="hPa" value="1019.4" />
</time>
<time from="2016-03-18T19:00:00" to="2016-03-19T01:00:00" period="3">
<!-- Valid from 2016-03-18T19:00:00 to 2016-03-19T01:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="mf/01n.32" />
<precipitation value="0" />
<!-- Valid at 2016-03-18T19:00:00 -->
<windDirection deg="265.3" code="W" name="West" />
<windSpeed mps="2.1" name="Light breeze" />
<temperature unit="celsius" value="6" />
<pressure unit="hPa" value="1018.0" />
</time>
<time from="2016-03-19T01:00:00" to="2016-03-19T07:00:00" period="0">
<!-- Valid from 2016-03-19T01:00:00 to 2016-03-19T07:00:00 -->
<symbol number="3" numberEx="3" name="Partly cloudy" var="mf/03n.35" />
<precipitation value="0" />
<!-- Valid at 2016-03-19T01:00:00 -->
<windDirection deg="256.0" code="WSW" name="West-southwest" />
<windSpeed mps="1.6" name="Light breeze" />
<temperature unit="celsius" value="1" />
<pressure unit="hPa" value="1019.1" />
</time>
<time from="2016-03-19T07:00:00" to="2016-03-19T13:00:00" period="1">
<!-- Valid from 2016-03-19T07:00:00 to 2016-03-19T13:00:00 -->
<symbol number="4" numberEx="4" name="Cloudy" var="04" />
<precipitation value="0" />
<!-- Valid at 2016-03-19T07:00:00 -->
<windDirection deg="304.5" code="NW" name="Northwest" />
<windSpeed mps="2.1" name="Light breeze" />
<temperature unit="celsius" value="1" />
<pressure unit="hPa" value="1019.0" />
</time>
<time from="2016-03-19T13:00:00" to="2016-03-19T19:00:00" period="2">
<!-- Valid from 2016-03-19T13:00:00 to 2016-03-19T19:00:00 -->
<symbol number="3" numberEx="3" name="Partly cloudy" var="03d" />
<precipitation value="0" />
<!-- Valid at 2016-03-19T13:00:00 -->
<windDirection deg="338.6" code="NNW" name="North-northwest" />
<windSpeed mps="1.9" name="Light breeze" />
<temperature unit="celsius" value="6" />
<pressure unit="hPa" value="1019.7" />
</time>
<time from="2016-03-19T19:00:00" to="2016-03-20T01:00:00" period="3">
<!-- Valid from 2016-03-19T19:00:00 to 2016-03-20T01:00:00 -->
<symbol number="2" numberEx="2" name="Fair" var="mf/02n.35" />
<precipitation value="0" />
<!-- Valid at 2016-03-19T19:00:00 -->
<windDirection deg="330.5" code="NNW" name="North-northwest" />
<windSpeed mps="2.3" name="Light breeze" />
<temperature unit="celsius" value="5" />
<pressure unit="hPa" value="1019.9" />
</time>
<time from="2016-03-20T01:00:00" to="2016-03-20T07:00:00" period="0">
<!-- Valid from 2016-03-20T01:00:00 to 2016-03-20T07:00:00 -->
<symbol number="3" numberEx="3" name="Partly cloudy" var="mf/03n.39" />
<precipitation value="0" />
<!-- Valid at 2016-03-20T01:00:00 -->
<windDirection deg="282.4" code="WNW" name="West-northwest" />
<windSpeed mps="1.6" name="Light breeze" />
<temperature unit="celsius" value="1" />
<pressure unit="hPa" value="1020.7" />
</time>
<time from="2016-03-20T07:00:00" to="2016-03-20T13:00:00" period="1">
<!-- Valid from 2016-03-20T07:00:00 to 2016-03-20T13:00:00 -->
<symbol number="3" numberEx="3" name="Partly cloudy" var="03d" />
<precipitation value="0" />
<!-- Valid at 2016-03-20T07:00:00 -->
<windDirection deg="283.8" code="WNW" name="West-northwest" />
<windSpeed mps="1.7" name="Light breeze" />
<temperature unit="celsius" value="1" />
<pressure unit="hPa" value="1019.8" />
</time>
<time from="2016-03-20T13:00:00" to="2016-03-20T19:00:00" period="2">
<!-- Valid from 2016-03-20T13:00:00 to 2016-03-20T19:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01d" />
<precipitation value="0" />
<!-- Valid at 2016-03-20T13:00:00 -->
<windDirection deg="316.8" code="NW" name="Northwest" />
<windSpeed mps="2.0" name="Light breeze" />
<temperature unit="celsius" value="7" />
<pressure unit="hPa" value="1018.5" />
</time>
<time from="2016-03-20T19:00:00" to="2016-03-21T01:00:00" period="3">
<!-- Valid from 2016-03-20T19:00:00 to 2016-03-21T01:00:00 -->
<symbol number="4" numberEx="4" name="Cloudy" var="04" />
<precipitation value="0" />
<!-- Valid at 2016-03-20T19:00:00 -->
<windDirection deg="344.0" code="NNW" name="North-northwest" />
<windSpeed mps="2.2" name="Light breeze" />
<temperature unit="celsius" value="4" />
<pressure unit="hPa" value="1016.8" />
</time>
<time from="2016-03-21T01:00:00" to="2016-03-21T07:00:00" period="0">
<!-- Valid from 2016-03-21T01:00:00 to 2016-03-21T07:00:00 -->
<symbol number="3" numberEx="3" name="Partly cloudy" var="mf/03n.42" />
<precipitation value="0" />
<!-- Valid at 2016-03-21T01:00:00 -->
<windDirection deg="324.9" code="NW" name="Northwest" />
<windSpeed mps="1.8" name="Light breeze" />
<temperature unit="celsius" value="3" />
<pressure unit="hPa" value="1017.8" />
</time>
<time from="2016-03-21T07:00:00" to="2016-03-21T13:00:00" period="1">
<!-- Valid from 2016-03-21T07:00:00 to 2016-03-21T13:00:00 -->
<symbol number="4" numberEx="4" name="Cloudy" var="04" />
<precipitation value="0" />
<!-- Valid at 2016-03-21T07:00:00 -->
<windDirection deg="301.0" code="WNW" name="West-northwest" />
<windSpeed mps="1.3" name="Light air" />
<temperature unit="celsius" value="1" />
<pressure unit="hPa" value="1018.2" />
</time>
<time from="2016-03-21T13:00:00" to="2016-03-21T19:00:00" period="2">
<!-- Valid from 2016-03-21T13:00:00 to 2016-03-21T19:00:00 -->
<symbol number="1" numberEx="1" name="Clear sky" var="01d" />
<precipitation value="0" />
<!-- Valid at 2016-03-21T13:00:00 -->
<windDirection deg="100.6" code="E" name="East" />
<windSpeed mps="0.6" name="Light air" />
<temperature unit="celsius" value="7" />
<pressure unit="hPa" value="1016.5" />
</time>
<time from="2016-03-21T19:00:00" to="2016-03-22T01:00:00" period="3">
<!-- Valid from 2016-03-21T19:00:00 to 2016-03-22T01:00:00 -->
<symbol number="2" numberEx="2" name="Fair" var="mf/02n.42" />
<precipitation value="0" />
<!-- Valid at 2016-03-21T19:00:00 -->
<windDirection deg="62.0" code="ENE" name="East-northeast" />
<windSpeed mps="2.2" name="Light breeze" />
<temperature unit="celsius" value="3" />
<pressure unit="hPa" value="1012.6" />
</time>
<time from="2016-03-22T01:00:00" to="2016-03-22T07:00:00" period="0">
<!-- Valid from 2016-03-22T01:00:00 to 2016-03-22T07:00:00 -->
<symbol number="4" numberEx="4" name="Cloudy" var="04" />
<precipitation value="0" />
<!-- Valid at 2016-03-22T01:00:00 -->
<windDirection deg="324.0" code="NW" name="Northwest" />
<windSpeed mps="0.5" name="Light air" />
<temperature unit="celsius" value="2" />
<pressure unit="hPa" value="1009.8" />
</time>
<time from="2016-03-22T07:00:00" to="2016-03-22T13:00:00" period="1">
<!-- Valid from 2016-03-22T07:00:00 to 2016-03-22T13:00:00 -->
<symbol number="9" numberEx="46" name="Light rain" var="46" />
<precipitation value="0.5" />
<!-- Valid at 2016-03-22T07:00:00 -->
<windDirection deg="245.9" code="WSW" name="West-southwest" />
<windSpeed mps="1.7" name="Light breeze" />
<temperature unit="celsius" value="2" />
<pressure unit="hPa" value="1006.4" />
</time>
<time from="2016-03-22T13:00:00" to="2016-03-22T19:00:00" period="2">
<!-- Valid from 2016-03-22T13:00:00 to 2016-03-22T19:00:00 -->
<symbol number="9" numberEx="46" name="Light rain" var="46" />
<precipitation value="0.8" />
<!-- Valid at 2016-03-22T13:00:00 -->
<windDirection deg="294.6" code="WNW" name="West-northwest" />
<windSpeed mps="3.1" name="Light breeze" />
<temperature unit="celsius" value="7" />
<pressure unit="hPa" value="1003.8" />
</time>
<time from="2016-03-22T19:00:00" to="2016-03-23T01:00:00" period="3">
<!-- Valid from 2016-03-22T19:00:00 to 2016-03-23T01:00:00 -->
<symbol number="3" numberEx="3" name="Partly cloudy" var="mf/03n.46" />
<precipitation value="0" />
<!-- Valid at 2016-03-22T19:00:00 -->
<windDirection deg="292.7" code="WNW" name="West-northwest" />
<windSpeed mps="3.0" name="Light breeze" />
<temperature unit="celsius" value="4" />
<pressure unit="hPa" value="1002.0" />
</time>
<time from="2016-03-23T01:00:00" to="2016-03-23T07:00:00" period="0">
<!-- Valid from 2016-03-23T01:00:00 to 2016-03-23T07:00:00 -->
<symbol number="3" numberEx="3" name="Partly cloudy" var="mf/03n.49" />
<precipitation value="0" />
<!-- Valid at 2016-03-23T01:00:00 -->
<windDirection deg="296.5" code="WNW" name="West-northwest" />
<windSpeed mps="2.8" name="Light breeze" />
<temperature unit="celsius" value="1" />
<pressure unit="hPa" value="1002.1" />
</time>
<time from="2016-03-23T07:00:00" to="2016-03-23T13:00:00" period="1">
<!-- Valid from 2016-03-23T07:00:00 to 2016-03-23T13:00:00 -->
<symbol number="5" numberEx="40" name="Light rain showers" var="40d" />
<precipitation value="0.7" />
<!-- Valid at 2016-03-23T07:00:00 -->
<windDirection deg="323.0" code="NW" name="Northwest" />
<windSpeed mps="2.5" name="Light breeze" />
<temperature unit="celsius" value="1" />
<pressure unit="hPa" value="1002.0" />
</time>
<time from="2016-03-23T13:00:00" to="2016-03-23T19:00:00" period="2">
<!-- Valid from 2016-03-23T13:00:00 to 2016-03-23T19:00:00 -->
<symbol number="9" numberEx="9" name="Rain" var="09" />
<precipitation value="1.7" />
<!-- Valid at 2016-03-23T13:00:00 -->
<windDirection deg="308.8" code="NW" name="Northwest" />
<windSpeed mps="3.8" name="Gentle breeze" />
<temperature unit="celsius" value="6" />
<pressure unit="hPa" value="1002.4" />
</time>
<time from="2016-03-23T19:00:00" to="2016-03-24T01:00:00" period="3">
<!-- Valid from 2016-03-23T19:00:00 to 2016-03-24T01:00:00 -->
<symbol number="2" numberEx="2" name="Fair" var="mf/02n.49" />
<precipitation value="0" />
<!-- Valid at 2016-03-23T19:00:00 -->
<windDirection deg="311.6" code="NW" name="Northwest" />
<windSpeed mps="3.1" name="Light breeze" />
<temperature unit="celsius" value="2" />
<pressure unit="hPa" value="1004.3" />
</time>
<time from="2016-03-24T01:00:00" to="2016-03-24T07:00:00" period="0">
<!-- Valid from 2016-03-24T01:00:00 to 2016-03-24T07:00:00 -->
<symbol number="4" numberEx="4" name="Cloudy" var="04" />
<precipitation value="0" />
<!-- Valid at 2016-03-24T01:00:00 -->
<windDirection deg="310.8" code="NW" name="Northwest" />
<windSpeed mps="3.3" name="Light breeze" />
<temperature unit="celsius" value="0" />
<pressure unit="hPa" value="1008.0" />
</time>
<time from="2016-03-24T07:00:00" to="2016-03-24T13:00:00" period="1">
<!-- Valid from 2016-03-24T07:00:00 to 2016-03-24T13:00:00 -->
<symbol number="4" numberEx="4" name="Cloudy" var="04" />
<precipitation value="0" />
<!-- Valid at 2016-03-24T07:00:00 -->
<windDirection deg="288.1" code="WNW" name="West-northwest" />
<windSpeed mps="2.3" name="Light breeze" />
<temperature unit="celsius" value="-1" />
<pressure unit="hPa" value="1010.3" />
</time>
<time from="2016-03-24T13:00:00" to="2016-03-24T19:00:00" period="2">
<!-- Valid from 2016-03-24T13:00:00 to 2016-03-24T19:00:00 -->
<symbol number="4" numberEx="4" name="Cloudy" var="04" />
<precipitation value="0" />
<!-- Valid at 2016-03-24T13:00:00 -->
<windDirection deg="274.1" code="W" name="West" />
<windSpeed mps="4.6" name="Gentle breeze" />
<temperature unit="celsius" value="5" />
<pressure unit="hPa" value="1009.0" />
</time>
<time from="2016-03-24T19:00:00" to="2016-03-25T01:00:00" period="3">
<!-- Valid from 2016-03-24T19:00:00 to 2016-03-25T01:00:00 -->
<symbol number="4" numberEx="4" name="Cloudy" var="04" />
<precipitation value="0" />
<!-- Valid at 2016-03-24T19:00:00 -->
<windDirection deg="234.1" code="SW" name="Southwest" />
<windSpeed mps="2.9" name="Light breeze" />
<temperature unit="celsius" value="3" />
<pressure unit="hPa" value="1007.2" />
</time>
</tabular>
</forecast>
</weatherdata>

728
test/lib/setup.js Normal file
View File

@@ -0,0 +1,728 @@
/* jshint -W097 */// jshint strict:false
/*jslint node: true */
// check if tmp directory exists
var fs = require('fs');
var path = require('path');
var child_process = require('child_process');
var rootDir = path.normalize(__dirname + '/../../');
var pkg = require(rootDir + 'package.json');
var debug = typeof v8debug === 'object';
pkg.main = pkg.main || 'main.js';
var adapterName = path.normalize(rootDir).replace(/\\/g, '/').split('/');
adapterName = adapterName[adapterName.length - 2];
var adapterStarted = false;
function getAppName() {
var parts = __dirname.replace(/\\/g, '/').split('/');
return parts[parts.length - 3].split('.')[0];
}
var appName = getAppName().toLowerCase();
var objects;
var states;
var pid = null;
function copyFileSync(source, target) {
var targetFile = target;
//if target is a directory a new file with the same name will be created
if (fs.existsSync(target)) {
if ( fs.lstatSync( target ).isDirectory() ) {
targetFile = path.join(target, path.basename(source));
}
}
try {
fs.writeFileSync(targetFile, fs.readFileSync(source));
}
catch (err) {
console.log("file copy error: " +source +" -> " + targetFile + " (error ignored)");
}
}
function copyFolderRecursiveSync(source, target, ignore) {
var files = [];
var base = path.basename(source);
if (base === adapterName) {
base = pkg.name;
}
//check if folder needs to be created or integrated
var targetFolder = path.join(target, base);
if (!fs.existsSync(targetFolder)) {
fs.mkdirSync(targetFolder);
}
//copy
if (fs.lstatSync(source).isDirectory()) {
files = fs.readdirSync(source);
files.forEach(function (file) {
if (ignore && ignore.indexOf(file) !== -1) {
return;
}
var curSource = path.join(source, file);
var curTarget = path.join(targetFolder, file);
if (fs.lstatSync(curSource).isDirectory()) {
// ignore grunt files
if (file.indexOf('grunt') !== -1) return;
if (file === 'chai') return;
if (file === 'mocha') return;
copyFolderRecursiveSync(curSource, targetFolder, ignore);
} else {
copyFileSync(curSource, curTarget);
}
});
}
}
if (!fs.existsSync(rootDir + 'tmp')) {
fs.mkdirSync(rootDir + 'tmp');
}
function storeOriginalFiles() {
console.log('Store original files...');
var dataDir = rootDir + 'tmp/' + appName + '-data/';
var f = fs.readFileSync(dataDir + 'objects.json');
var objects = JSON.parse(f.toString());
if (objects['system.adapter.admin.0'] && objects['system.adapter.admin.0'].common) {
objects['system.adapter.admin.0'].common.enabled = false;
}
if (objects['system.adapter.admin.1'] && objects['system.adapter.admin.1'].common) {
objects['system.adapter.admin.1'].common.enabled = false;
}
fs.writeFileSync(dataDir + 'objects.json.original', JSON.stringify(objects));
try {
f = fs.readFileSync(dataDir + 'states.json');
fs.writeFileSync(dataDir + 'states.json.original', f);
}
catch (err) {
console.log('no states.json found - ignore');
}
}
function restoreOriginalFiles() {
console.log('restoreOriginalFiles...');
var dataDir = rootDir + 'tmp/' + appName + '-data/';
var f = fs.readFileSync(dataDir + 'objects.json.original');
fs.writeFileSync(dataDir + 'objects.json', f);
try {
f = fs.readFileSync(dataDir + 'states.json.original');
fs.writeFileSync(dataDir + 'states.json', f);
}
catch (err) {
console.log('no states.json.original found - ignore');
}
}
function checkIsAdapterInstalled(cb, counter, customName) {
customName = customName || pkg.name.split('.').pop();
counter = counter || 0;
var dataDir = rootDir + 'tmp/' + appName + '-data/';
console.log('checkIsAdapterInstalled...');
try {
var f = fs.readFileSync(dataDir + 'objects.json');
var objects = JSON.parse(f.toString());
if (objects['system.adapter.' + customName + '.0']) {
console.log('checkIsAdapterInstalled: ready!');
setTimeout(function () {
if (cb) cb();
}, 100);
return;
} else {
console.warn('checkIsAdapterInstalled: still not ready');
}
} catch (err) {
}
if (counter > 20) {
console.error('checkIsAdapterInstalled: Cannot install!');
if (cb) cb('Cannot install');
} else {
console.log('checkIsAdapterInstalled: wait...');
setTimeout(function() {
checkIsAdapterInstalled(cb, counter + 1);
}, 1000);
}
}
function checkIsControllerInstalled(cb, counter) {
counter = counter || 0;
var dataDir = rootDir + 'tmp/' + appName + '-data/';
console.log('checkIsControllerInstalled...');
try {
var f = fs.readFileSync(dataDir + 'objects.json');
var objects = JSON.parse(f.toString());
if (objects['system.adapter.admin.0']) {
console.log('checkIsControllerInstalled: installed!');
setTimeout(function () {
if (cb) cb();
}, 100);
return;
}
} catch (err) {
}
if (counter > 20) {
console.log('checkIsControllerInstalled: Cannot install!');
if (cb) cb('Cannot install');
} else {
console.log('checkIsControllerInstalled: wait...');
setTimeout(function() {
checkIsControllerInstalled(cb, counter + 1);
}, 1000);
}
}
function installAdapter(customName, cb) {
if (typeof customName === 'function') {
cb = customName;
customName = null;
}
customName = customName || pkg.name.split('.').pop();
console.log('Install adapter...');
var startFile = 'node_modules/' + appName + '.js-controller/' + appName + '.js';
// make first install
if (debug) {
child_process.execSync('node ' + startFile + ' add ' + customName + ' --enabled false', {
cwd: rootDir + 'tmp',
stdio: [0, 1, 2]
});
checkIsAdapterInstalled(function (error) {
if (error) console.error(error);
console.log('Adapter installed.');
if (cb) cb();
});
} else {
// add controller
var _pid = child_process.fork(startFile, ['add', customName, '--enabled', 'false'], {
cwd: rootDir + 'tmp',
stdio: [0, 1, 2, 'ipc']
});
waitForEnd(_pid, function () {
checkIsAdapterInstalled(function (error) {
if (error) console.error(error);
console.log('Adapter installed.');
if (cb) cb();
});
});
}
}
function waitForEnd(_pid, cb) {
if (!_pid) {
cb(-1, -1);
return;
}
_pid.on('exit', function (code, signal) {
if (_pid) {
_pid = null;
cb(code, signal);
}
});
_pid.on('close', function (code, signal) {
if (_pid) {
_pid = null;
cb(code, signal);
}
});
}
function installJsController(cb) {
console.log('installJsController...');
if (!fs.existsSync(rootDir + 'tmp/node_modules/' + appName + '.js-controller') ||
!fs.existsSync(rootDir + 'tmp/' + appName + '-data')) {
// try to detect appName.js-controller in node_modules/appName.js-controller
// travis CI installs js-controller into node_modules
if (fs.existsSync(rootDir + 'node_modules/' + appName + '.js-controller')) {
console.log('installJsController: no js-controller => copy it from "' + rootDir + 'node_modules/' + appName + '.js-controller"');
// copy all
// stop controller
console.log('Stop controller if running...');
var _pid;
if (debug) {
// start controller
_pid = child_process.exec('node ' + appName + '.js stop', {
cwd: rootDir + 'node_modules/' + appName + '.js-controller',
stdio: [0, 1, 2]
});
} else {
_pid = child_process.fork(appName + '.js', ['stop'], {
cwd: rootDir + 'node_modules/' + appName + '.js-controller',
stdio: [0, 1, 2, 'ipc']
});
}
waitForEnd(_pid, function () {
// copy all files into
if (!fs.existsSync(rootDir + 'tmp')) fs.mkdirSync(rootDir + 'tmp');
if (!fs.existsSync(rootDir + 'tmp/node_modules')) fs.mkdirSync(rootDir + 'tmp/node_modules');
if (!fs.existsSync(rootDir + 'tmp/node_modules/' + appName + '.js-controller')){
console.log('Copy js-controller...');
copyFolderRecursiveSync(rootDir + 'node_modules/' + appName + '.js-controller', rootDir + 'tmp/node_modules/');
}
console.log('Setup js-controller...');
var __pid;
if (debug) {
// start controller
_pid = child_process.exec('node ' + appName + '.js setup first --console', {
cwd: rootDir + 'tmp/node_modules/' + appName + '.js-controller',
stdio: [0, 1, 2]
});
} else {
__pid = child_process.fork(appName + '.js', ['setup', 'first', '--console'], {
cwd: rootDir + 'tmp/node_modules/' + appName + '.js-controller',
stdio: [0, 1, 2, 'ipc']
});
}
waitForEnd(__pid, function () {
checkIsControllerInstalled(function () {
// change ports for object and state DBs
var config = require(rootDir + 'tmp/' + appName + '-data/' + appName + '.json');
config.objects.port = 19001;
config.states.port = 19000;
fs.writeFileSync(rootDir + 'tmp/' + appName + '-data/' + appName + '.json', JSON.stringify(config, null, 2));
console.log('Setup finished.');
copyAdapterToController();
installAdapter(function () {
storeOriginalFiles();
if (cb) cb(true);
});
});
});
});
} else {
// check if port 9000 is free, else admin adapter will be added to running instance
var client = new require('net').Socket();
client.connect(9000, '127.0.0.1', function() {
console.error('Cannot initiate fisrt run of test, because one instance of application is running on this PC. Stop it and repeat.');
process.exit(0);
});
setTimeout(function () {
client.destroy();
if (!fs.existsSync(rootDir + 'tmp/node_modules/' + appName + '.js-controller')) {
console.log('installJsController: no js-controller => install from git');
child_process.execSync('npm install https://github.com/' + appName + '/' + appName + '.js-controller/tarball/master --prefix ./ --production', {
cwd: rootDir + 'tmp/',
stdio: [0, 1, 2]
});
} else {
console.log('Setup js-controller...');
var __pid;
if (debug) {
// start controller
child_process.exec('node ' + appName + '.js setup first', {
cwd: rootDir + 'tmp/node_modules/' + appName + '.js-controller',
stdio: [0, 1, 2]
});
} else {
child_process.fork(appName + '.js', ['setup', 'first'], {
cwd: rootDir + 'tmp/node_modules/' + appName + '.js-controller',
stdio: [0, 1, 2, 'ipc']
});
}
}
// let npm install admin and run setup
checkIsControllerInstalled(function () {
var _pid;
if (fs.existsSync(rootDir + 'node_modules/' + appName + '.js-controller/' + appName + '.js')) {
_pid = child_process.fork(appName + '.js', ['stop'], {
cwd: rootDir + 'node_modules/' + appName + '.js-controller',
stdio: [0, 1, 2, 'ipc']
});
}
waitForEnd(_pid, function () {
// change ports for object and state DBs
var config = require(rootDir + 'tmp/' + appName + '-data/' + appName + '.json');
config.objects.port = 19001;
config.states.port = 19000;
fs.writeFileSync(rootDir + 'tmp/' + appName + '-data/' + appName + '.json', JSON.stringify(config, null, 2));
copyAdapterToController();
installAdapter(function () {
storeOriginalFiles();
if (cb) cb(true);
});
});
});
}, 1000);
}
} else {
setTimeout(function () {
console.log('installJsController: js-controller installed');
if (cb) cb(false);
}, 0);
}
}
function copyAdapterToController() {
console.log('Copy adapter...');
// Copy adapter to tmp/node_modules/appName.adapter
copyFolderRecursiveSync(rootDir, rootDir + 'tmp/node_modules/', ['.idea', 'test', 'tmp', '.git', appName + '.js-controller']);
console.log('Adapter copied.');
}
function clearControllerLog() {
var dirPath = rootDir + 'tmp/log';
var files;
try {
if (fs.existsSync(dirPath)) {
console.log('Clear controller log...');
files = fs.readdirSync(dirPath);
} else {
console.log('Create controller log directory...');
files = [];
fs.mkdirSync(dirPath);
}
} catch(e) {
console.error('Cannot read "' + dirPath + '"');
return;
}
if (files.length > 0) {
try {
for (var i = 0; i < files.length; i++) {
var filePath = dirPath + '/' + files[i];
fs.unlinkSync(filePath);
}
console.log('Controller log cleared');
} catch (err) {
console.error('cannot clear log: ' + err);
}
}
}
function clearDB() {
var dirPath = rootDir + 'tmp/yunkong2-data/sqlite';
var files;
try {
if (fs.existsSync(dirPath)) {
console.log('Clear sqlite DB...');
files = fs.readdirSync(dirPath);
} else {
console.log('Create controller log directory...');
files = [];
fs.mkdirSync(dirPath);
}
} catch(e) {
console.error('Cannot read "' + dirPath + '"');
return;
}
if (files.length > 0) {
try {
for (var i = 0; i < files.length; i++) {
var filePath = dirPath + '/' + files[i];
fs.unlinkSync(filePath);
}
console.log('Clear sqlite DB');
} catch (err) {
console.error('cannot clear DB: ' + err);
}
}
}
function setupController(cb) {
installJsController(function (isInited) {
clearControllerLog();
clearDB();
if (!isInited) {
restoreOriginalFiles();
copyAdapterToController();
}
// read system.config object
var dataDir = rootDir + 'tmp/' + appName + '-data/';
var objs;
try {
objs = fs.readFileSync(dataDir + 'objects.json');
objs = JSON.parse(objs);
}
catch (e) {
console.log('ERROR reading/parsing system configuration. Ignore');
objs = {'system.config': {}};
}
if (!objs || !objs['system.config']) {
objs = {'system.config': {}};
}
if (cb) cb(objs['system.config']);
});
}
function startAdapter(objects, states, callback) {
if (adapterStarted) {
console.log('Adapter already started ...');
if (callback) callback(objects, states);
return;
}
adapterStarted = true;
console.log('startAdapter...');
if (fs.existsSync(rootDir + 'tmp/node_modules/' + pkg.name + '/' + pkg.main)) {
try {
if (debug) {
// start controller
pid = child_process.exec('node node_modules/' + pkg.name + '/' + pkg.main + ' --console silly', {
cwd: rootDir + 'tmp',
stdio: [0, 1, 2]
});
} else {
// start controller
pid = child_process.fork('node_modules/' + pkg.name + '/' + pkg.main, ['--console', 'silly'], {
cwd: rootDir + 'tmp',
stdio: [0, 1, 2, 'ipc']
});
}
} catch (error) {
console.error(JSON.stringify(error));
}
} else {
console.error('Cannot find: ' + rootDir + 'tmp/node_modules/' + pkg.name + '/' + pkg.main);
}
if (callback) callback(objects, states);
}
function startController(isStartAdapter, onObjectChange, onStateChange, callback) {
if (typeof isStartAdapter === 'function') {
callback = onStateChange;
onStateChange = onObjectChange;
onObjectChange = isStartAdapter;
isStartAdapter = true;
}
if (onStateChange === undefined) {
callback = onObjectChange;
onObjectChange = undefined;
}
if (pid) {
console.error('Controller is already started!');
} else {
console.log('startController...');
adapterStarted = false;
var isObjectConnected;
var isStatesConnected;
var Objects = require(rootDir + 'tmp/node_modules/' + appName + '.js-controller/lib/objects/objectsInMemServer');
objects = new Objects({
connection: {
"type" : "file",
"host" : "127.0.0.1",
"port" : 19001,
"user" : "",
"pass" : "",
"noFileCache": false,
"connectTimeout": 2000
},
logger: {
silly: function (msg) {
console.log(msg);
},
debug: function (msg) {
console.log(msg);
},
info: function (msg) {
console.log(msg);
},
warn: function (msg) {
console.warn(msg);
},
error: function (msg) {
console.error(msg);
}
},
connected: function () {
isObjectConnected = true;
if (isStatesConnected) {
console.log('startController: started!');
if (isStartAdapter) {
startAdapter(objects, states, callback);
} else {
if (callback) {
callback(objects, states);
callback = null;
}
}
}
},
change: onObjectChange
});
// Just open in memory DB itself
var States = require(rootDir + 'tmp/node_modules/' + appName + '.js-controller/lib/states/statesInMemServer');
states = new States({
connection: {
type: 'file',
host: '127.0.0.1',
port: 19000,
options: {
auth_pass: null,
retry_max_delay: 15000
}
},
logger: {
silly: function (msg) {
console.log(msg);
},
debug: function (msg) {
console.log(msg);
},
info: function (msg) {
console.log(msg);
},
warn: function (msg) {
console.log(msg);
},
error: function (msg) {
console.log(msg);
}
},
connected: function () {
isStatesConnected = true;
if (isObjectConnected) {
console.log('startController: started!!');
if (isStartAdapter) {
startAdapter(objects, states, callback);
} else {
if (callback) {
callback(objects, states);
callback = null;
}
}
}
},
change: onStateChange
});
}
}
function stopAdapter(cb) {
if (!pid) {
console.error('Controller is not running!');
if (cb) {
setTimeout(function () {
cb(false);
}, 0);
}
} else {
adapterStarted = false;
pid.on('exit', function (code, signal) {
if (pid) {
console.log('child process terminated due to receipt of signal ' + signal);
if (cb) cb();
pid = null;
}
});
pid.on('close', function (code, signal) {
if (pid) {
if (cb) cb();
pid = null;
}
});
pid.kill('SIGTERM');
}
}
function _stopController() {
if (objects) {
objects.destroy();
objects = null;
}
if (states) {
states.destroy();
states = null;
}
}
function stopController(cb) {
var timeout;
if (objects) {
console.log('Set system.adapter.' + pkg.name + '.0');
objects.setObject('system.adapter.' + pkg.name + '.0', {
common:{
enabled: false
}
});
}
stopAdapter(function () {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
_stopController();
if (cb) {
cb(true);
cb = null;
}
});
timeout = setTimeout(function () {
timeout = null;
console.log('child process NOT terminated');
_stopController();
if (cb) {
cb(false);
cb = null;
}
pid = null;
}, 5000);
}
// Setup the adapter
function setAdapterConfig(common, native, instance) {
var objects = JSON.parse(fs.readFileSync(rootDir + 'tmp/' + appName + '-data/objects.json').toString());
var id = 'system.adapter.' + adapterName.split('.').pop() + '.' + (instance || 0);
if (common) objects[id].common = common;
if (native) objects[id].native = native;
fs.writeFileSync(rootDir + 'tmp/' + appName + '-data/objects.json', JSON.stringify(objects));
}
// Read config of the adapter
function getAdapterConfig(instance) {
var objects = JSON.parse(fs.readFileSync(rootDir + 'tmp/' + appName + '-data/objects.json').toString());
var id = 'system.adapter.' + adapterName.split('.').pop() + '.' + (instance || 0);
return objects[id];
}
if (typeof module !== undefined && module.parent) {
module.exports.getAdapterConfig = getAdapterConfig;
module.exports.setAdapterConfig = setAdapterConfig;
module.exports.startController = startController;
module.exports.stopController = stopController;
module.exports.setupController = setupController;
module.exports.stopAdapter = stopAdapter;
module.exports.startAdapter = startAdapter;
module.exports.installAdapter = installAdapter;
module.exports.appName = appName;
module.exports.adapterName = adapterName;
module.exports.adapterStarted = adapterStarted;
}

1297
test/lib/warnings.json Normal file

File diff suppressed because it is too large Load Diff

135
test/testFunctions.js Normal file
View File

@@ -0,0 +1,135 @@
const expect = require('chai').expect;
const setup = require(__dirname + '/lib/setup');
let name = __dirname.replace(/\\/g, '/').split('/');
name = name[name.length - 2].split('.')[1];
let objects = null;
let states = null;
let onStateChanged = null;
let onObjectChanged = null;
function checkConnectionOfAdapter(cb, counter) {
counter = counter || 0;
if (counter > 20) {
cb && cb('Cannot check connection');
return;
}
states.getState('system.adapter.' + name + '.0.alive', function (err, state) {
if (err) console.error(err);
if (state && state.val) {
cb && cb();
} else {
setTimeout(function () {
checkConnectionOfAdapter(cb, counter + 1);
}, 1000);
}
});
}
function checkValueOfState(id, value, cb, counter) {
counter = counter || 0;
if (counter > 20) {
cb && cb('Cannot check value Of State ' + id);
return;
}
states.getState(id, function (err, state) {
if (err) console.error(err);
if (value === null && !state) {
cb && cb();
} else
if (state && (value === undefined || state.val === value)) {
cb && cb();
} else {
setTimeout(function () {
checkValueOfState(id, value, cb, counter + 1);
}, 500);
}
});
}
describe('Test ' + name, function () {
before('Test ' + name + ': Start js-controller', function (_done) {
this.timeout(600000); // because of first install from npm
setup.setupController(function () {
const config = setup.getAdapterConfig();
// enable adapter
config.common.enabled = true;
config.common.loglevel = 'debug';
config.native.location = __dirname + '/lib/forecast.xml';
config.native.language = '';
config.native.sendTranslations = false;
setup.setAdapterConfig(config.common, config.native);
setup.startController(true, function (id, obj) {
if (onObjectChanged) onObjectChanged(id, obj);
}, function (id, state) {
console.log(id + ': ' + state.val);
if (onStateChanged) onStateChanged(id, state);
},
function (_objects, _states) {
objects = _objects;
states = _states;
states.subscribe('*');
objects.subscribe('*');
_done();
});
});
});
it('Test ' + name + ': Check if adapter started', function (done) {
this.timeout(5000);
checkConnectionOfAdapter(done);
});
it('Test ' + name + ': channel must have name of city', function (done) {
setTimeout(function () {
objects.getObject('yr.0.forecast', function (err, obj) {
expect(err).to.be.not.ok;
expect(obj).to.be.ok;
expect(obj.common.name).to.be.equal('yr.no forecast forecast.xml');
done();
});
}, 500);
});
it('Test ' + name + ': check states', function (done) {
this.timeout(5000);
setTimeout(function () {
states.getState('yr.0.forecast.day0.temperatureMin', function (err, state) {
expect(err).to.be.not.ok;
expect(state).to.be.ok;
expect(state.val).to.be.not.undefined;
expect(state.val).to.be.a('number');
states.getState('yr.0.forecast.day0.temperatureMax', function (err, state) {
expect(err).to.be.not.ok;
expect(state).to.be.ok;
expect(state.val).to.be.not.undefined;
expect(state.val).to.be.a('number');
states.getState('yr.0.forecast.day0.temperatureActual', function (err, state) {
expect(err).to.be.not.ok;
expect(state).to.be.ok;
expect(state.val).to.be.not.undefined;
expect(state.val).to.be.a('number');
done();
});
});
});
}, 100);
});
after('Test ' + name + ': Stop js-controller', function (done) {
this.timeout(7000);
setup.stopController(function (normalTerminated) {
console.log('Adapter normal terminated: ' + normalTerminated);
done();
});
});
});

91
test/testPackageFiles.js Normal file
View File

@@ -0,0 +1,91 @@
/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
/* jshint expr: true */
var expect = require('chai').expect;
var fs = require('fs');
describe('Test package.json and io-package.json', function() {
it('Test package files', function (done) {
console.log();
var fileContentIOPackage = fs.readFileSync(__dirname + '/../io-package.json', 'utf8');
var ioPackage = JSON.parse(fileContentIOPackage);
var fileContentNPMPackage = fs.readFileSync(__dirname + '/../package.json', 'utf8');
var npmPackage = JSON.parse(fileContentNPMPackage);
expect(ioPackage).to.be.an('object');
expect(npmPackage).to.be.an('object');
expect(ioPackage.common.version, 'ERROR: Version number in io-package.json needs to exist').to.exist;
expect(npmPackage.version, 'ERROR: Version number in package.json needs to exist').to.exist;
expect(ioPackage.common.version, 'ERROR: Version numbers in package.json and io-package.json needs to match').to.be.equal(npmPackage.version);
if (!ioPackage.common.news || !ioPackage.common.news[ioPackage.common.version]) {
console.log('WARNING: No news entry for current version exists in io-package.json, no rollback in Admin possible!');
console.log();
}
expect(npmPackage.author, 'ERROR: Author in package.json needs to exist').to.exist;
expect(ioPackage.common.authors, 'ERROR: Authors in io-package.json needs to exist').to.exist;
if (ioPackage.common.name.indexOf('template') !== 0) {
if (Array.isArray(ioPackage.common.authors)) {
expect(ioPackage.common.authors.length, 'ERROR: Author in io-package.json needs to be set').to.not.be.equal(0);
if (ioPackage.common.authors.length === 1) {
expect(ioPackage.common.authors[0], 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
}
}
else {
expect(ioPackage.common.authors, 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
}
}
else {
console.log('WARNING: Testing for set authors field in io-package skipped because template adapter');
console.log();
}
expect(fs.existsSync(__dirname + '/../README.md'), 'ERROR: README.md needs to exist! Please create one with description, detail information and changelog. English is mandatory.').to.be.true;
if (!ioPackage.common.titleLang || typeof ioPackage.common.titleLang !== 'object') {
console.log('WARNING: titleLang is not existing in io-package.json. Please add');
console.log();
}
if (
ioPackage.common.title.indexOf('yunkong2') !== -1 ||
ioPackage.common.title.indexOf('yunkong2') !== -1 ||
ioPackage.common.title.indexOf('adapter') !== -1 ||
ioPackage.common.title.indexOf('Adapter') !== -1
) {
console.log('WARNING: title contains Adapter or yunkong2. It is clear anyway, that it is adapter for yunkong2.');
console.log();
}
if (ioPackage.common.name.indexOf('vis-') !== 0) {
if (!ioPackage.common.materialize || !fs.existsSync(__dirname + '/../admin/index_m.html') || !fs.existsSync(__dirname + '/../gulpfile.js')) {
console.log('WARNING: Admin3 support is missing! Please add it');
console.log();
}
if (ioPackage.common.materialize) {
expect(fs.existsSync(__dirname + '/../admin/index_m.html'), 'Admin3 support is enabled in io-package.json, but index_m.html is missing!').to.be.true;
}
}
var licenseFileExists = fs.existsSync(__dirname + '/../LICENSE');
var fileContentReadme = fs.readFileSync(__dirname + '/../README.md', 'utf8');
if (fileContentReadme.indexOf('## Changelog') === -1) {
console.log('Warning: The README.md should have a section ## Changelog');
console.log();
}
expect((licenseFileExists || fileContentReadme.indexOf('## License') !== -1), 'A LICENSE must exist as LICENSE file or as part of the README.md').to.be.true;
if (!licenseFileExists) {
console.log('Warning: The License should also exist as LICENSE file');
console.log();
}
if (fileContentReadme.indexOf('## License') === -1) {
console.log('Warning: The README.md should also have a section ## License to be shown in Admin3');
console.log();
}
done();
});
});