Australian Bureau of Meteorology integration with OpenHAB

Hi Kris,

Change the definition of time for val to var, “var String time = …”, I edited my original post to reflect this.

I noticed some observation data does not appear at certain times. I guess if there is no wind, BOM don’t publish a wind speed. You could check the raw json data from BOM in your browser.

Thanks, that fixed that.

The wind speed is present, as seen here:

http://www.bom.gov.au/fwo/IDN60901/IDN60901.94766.json

I do not see in the logs the rule running every 5 minutes, nothing is logged at all.

But it shows up NULL in your rules. If i update them manually, they display fine in the widget.


rule "Get weather observation data from BOM"
when
        Time cron "0 */5 * ? * *" // update every 5 minutes
then
        logInfo("BOM data","reading observation data")
                val URL url = new URL("http://www.bom.gov.au/fwo/IDN60901/IDN60901.94766.json");
                val InputStreamReader instream = new InputStreamReader(url.openStream())
                var StringBuilder sb = new StringBuilder();
                var CharBuffer cb = CharBuffer.allocate(1024);

        var int read = instream.read ( cb );
        while(read != -1) {
        sb.append(cb.array(), 0, read )
                cb.clear
                read = instream.read( cb )
        }
        instream.close();

        val String bom_data = sb.toString();

        var String time = transform("JSONPATH", "$.observations.data[0].local_date_time", bom_data)
        time = time.substring(time.indexOf('/')+1,time.length())
        logInfo("BOM data","observation_time="+time)
        postUpdate("BOM_Observation_Time", time)

        val air_temp = transform("JSONPATH", "$.observations.data[0].air_temp", bom_data)
        logInfo("BOM data","air_temp="+air_temp)
        postUpdate("BOM_AirTemp", air_temp)
        val apparent_t = transform("JSONPATH", "$.observations.data[0].apparent_t", bom_data)
        logInfo("BOM data","apparent_t="+apparent_t)
        postUpdate("BOM_ApparentTemp", apparent_t)
        val wind_dir = transform("JSONPATH", "$.observations.data[0].wind_dir", bom_data)
        logInfo("BOM data","wind_dir="+wind_dir)
        postUpdate("BOM_WindDir", wind_dir)
        val wind_spd = transform("JSONPATH", "$.observations.data[0].wind_spd_kmh", bom_data)
        logInfo("BOM data","wind_spd="+wind_spd)
        postUpdate("BOM_WindSpeed", wind_spd)
        val rain = transform("JSONPATH", "$.observations.data[0].rain_trace", bom_data)
        logInfo("BOM data","rain="+rain)
        postUpdate("BOM_Rain_Amount", rain)
end

Edit : FIXED

I rebooted openHab and it started to work! Very odd. Thanks James!

Hi All

I have successfully implemented the above OpenHAB rule but have noticed the entire contents of the xml file end up in the OpenHAB log file. Is there anyway to stop this from happening?

Hi Adam

You can remove the logInfos from the rule

Regards

Hi Kris

I have commented out all loginfos but still get the whole xml file showing in the log

                <element type="precipitation_range">0 to 1 mm</element>
                <element type="air_temperature_minimum" units="Celsius">21</element>
                <element type="air_temperature_maximum" units="Celsius">36</element>
                <text type="precis">Possible shower.</text>
                <text type="probability_of_precipitation">40%</text>
            </forecast-period>
            <forecast-period index="2" start-time-local="2019-02-07T00:00:00+10:30" end-time-local="2019-02-08T00:00:00+10:30" start-time-utc="2019-02-06T13:30:00Z" end-time-utc="2019-02-07T13:30:00Z">
                <element type="forecast_icon_code">3</element>
                <element type="air_temperature_minimum" units="Celsius">21</element>
                <element type="air_temperature_maximum" units="Celsius">37</element>
                <text type="precis">Mostly sunny.</text>
                <text type="probability_of_precipitation">10%</text>
            </forecast-period>
            <forecast-period index="3" start-time-local="2019-02-08T00:00:00+10:30" end-time-local="2019-02-09T00:00:00+10:30" start-time-utc="2019-02-07T13:30:00Z" end-time-utc="2019-02-08T13:30:00Z">
                <element type="forecast_icon_code">3</element>
                <element type="air_temperature_minimum" units="Celsius">15</element>
                <element type="air_temperature_maximum" units="Celsius">29</element>
                <text type="precis">Mostly sunny.</text>
                <text type="probability_of_precipitation">0%</text>
            </forecast-period>
            <forecast-period index="4" start-time-local="2019-02-09T00:00:00+10:30" end-time-local="2019-02-10T00:00:00+10:30" start-time-utc="2019-02-08T13:30:00Z" end-time-utc="2019-02-09T13:30:00Z">
                <element type="forecast_icon_code">1</element>
                <element type="air_temperature_minimum" units="Celsius">10</element>
                <element type="air_temperature_maximum" units="Celsius">28</element>
                <text type="precis">Sunny.</text>
                <text type="probability_of_precipitation">0%</text>
            </forecast-period>
            <forecast-period index="5" start-time-local="2019-02-10T00:00:00+10:30" end-time-local="2019-02-11T00:00:00+10:30" start-time-utc="2019-02-09T13:30:00Z" end-time-utc="2019-02-10T13:30:00Z">
                <element type="forecast_icon_code">1</element>
                <element type="air_temperature_minimum" units="Celsius">11</element>
                <element type="air_temperature_maximum" units="Celsius">30</element>
                <text type="precis">Sunny.</text>
                <text type="probability_of_precipitation">0%</text>
            </forecast-period>
            <forecast-period index="6" start-time-local="2019-02-11T00:00:00+10:30" end-time-local="2019-02-12T00:00:00+10:30" start-time-utc="2019-02-10T13:30:00Z" end-time-utc="2019-02-11T13:30:00Z">
                <element type="forecast_icon_code">3</element>
                <element type="air_temperature_minimum" units="Celsius">14</element>
                <element type="air_temperature_maximum" units="Celsius">32</element>
                <text type="precis">Mostly sunny.</text>
                <text type="probability_of_precipitation">0%</text>
            </forecast-period>
        </area>
    </forecast>
</product>
' to a state type which item 'BOM_Forecast_Icon_Code_6' accepts: [DecimalType, QuantityType, UnDefType].

All 30,000 lines of it… When it does run its the only thing in the whole log file…

2019-02-05 13:30:02.408 [WARN ] [rthome.model.script.actions.BusEvent] - Cannot convert '<?xml version="1.0" encoding="UTF-8"?>
<product version="1.7" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.bom.gov.au/schema/v1.7/product.xsd">
    <amoc>
        <source>
            <sender>Australian Government Bureau of Meteorology</sender>
            <region>South Australia</region>
            <office>SARO</office>
            <copyright>http://www.bom.gov.au/other/copyright.shtml</copyright>
            <disclaimer>http://www.bom.gov.au/other/disclaimer.shtml</disclaimer>
        </source>
        <identifier>IDS10044</identifier>
        <issue-time-utc>2019-02-04T18:45:00Z</issue-time-utc>
        <issue-time-local tz="CDT">2019-02-05T05:15:00+10:30</issue-time-local>
        <sent-time>2019-02-04T18:45:08Z</sent-time>
        <expiry-time>2019-02-05T18:45:00Z</expiry-time>
        <validity-bgn-time-local tz="CDT">2019-02-05T05:00:00+10:30</validity-bgn-time-local>
        <validity-end-time-local tz="CDT">2019-02-11T23:59:59+10:30</validity-end-time-local>
        <next-routine-issue-time-utc>2019-02-05T05:30:00Z</next-routine-issue-time-utc>
        <next-routine-issue-time-local tz="CDT">2019-02-05T16:00:00+10:30</next-routine-issue-time-local>
        <status>O</status>
        <service>WSP</service>
        <sub-service>FPR</sub-service>
        <product-type>F</product-type>
        <phase>NEW</phase>
    </amoc>
    <forecast>
        <area aac="SA_FA001" description="South Australia" type="region"/>
        <area aac="SA_PW001" description="Adelaide Metropolitan" type="public-district" parent-aac="SA_FA001"/>
        <area aac="SA_PT001" description="Adelaide" type="location" parent-aac="SA_PW001">
            <forecast-period index="0" start-time-local="2019-02-05T05:00:00+10:30" end-time-local="2019-02-06T00:00:00+10:30" start-time-utc="2019-02-04T18:30:00Z" end-time-utc="2019-02-05T13:30:00Z">
                <element type="forecast_icon_code">3</element>
                <element type="air_temperature_maximum" units="Celsius">32</element>
                <text type="precis">Mostly sunny.</text>
                <text type="probability_of_precipitation">0%</text>
            </forecast-period>

Can you provide a

log:display

from the console, that certainly doesn’t happen to me with the rule above.

sorry i’m on windows 10, do you mean a copy of the openhab.log file? i did paste part of the log file above. Australian Bureau of Meteorology integration with OpenHAB - #122 by menzy

I have also checked my persistence & it looks like it’s not persisting anything in the forecast rule. the observation rule is working great.

here is my complete rule file

import java.io.InputStreamReader;
import java.nio.CharBuffer;
import java.net.URL;
import java.lang.StringBuilder;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

rule "Get weather forecast data from BOM"
when
	Time cron "0 */5 * ? * *" // update every 10 minutes
//	Time cron "0 0 */6 ? * *" // update every 6 hours
then    
	//logInfo("BOM data","reading forecast data")
	val URL url = new URL("ftp://ftp.bom.gov.au/anon/gen/fwo/IDS10044.xml");
    val InputStreamReader instream = new InputStreamReader(url.openStream())
	var StringBuilder sb = new StringBuilder();
	var CharBuffer cb = CharBuffer.allocate(1024);

	var int read = instream.read ( cb );
	while(read != -1) {
    	sb.append(cb.array(), 0, read )
		cb.clear
		read = instream.read( cb )
	}
	instream.close();

	val String bom_data = sb.toString();	

	for(var int i=0; i<7; i++)
	{
		//logInfo("BOM data","day index="+i)
		val String start_time = transform ("XPATH", "//forecast/area[@aac='SA_PT013']/forecast-period[@index='"+i+"']/@start-time-local", bom_data)
		//logInfo("BOM data","start_time="+start_time)
		postUpdate("BOM_Date_"+i, start_time)

		val String air_temperature_maximum = transform ("XPATH", "//forecast/area[@aac='SA_PT013']/forecast-period[@index='"+i+"']/element[@type='air_temperature_maximum']/text()", bom_data)
		//logInfo("BOM data","air_temperature_maximum="+air_temperature_maximum)
		postUpdate("BOM_Temp_Max_"+i, air_temperature_maximum)

		val String air_temperature_minimum = transform ("XPATH", "//forecast/area[@aac='SA_PT013']/forecast-period[@index='"+i+"']/element[@type='air_temperature_minimum']/text()", bom_data)
		//logInfo("BOM data","air_temperature_minimum="+air_temperature_minimum)
		postUpdate("BOM_Temp_Min_"+i, air_temperature_minimum)

		val String precipitation_range = transform ("XPATH", "//forecast/area[@aac='SA_PT013']/forecast-period[@index='"+i+"']/element[@type='precipitation_range']/text()", bom_data)
		//logInfo("BOM data","precipitation_range="+precipitation_range)
		postUpdate("BOM_Precipitation_Range_"+i, precipitation_range)

		val String forecast_icon_code = transform ("XPATH", "//forecast/area[@aac='SA_PT013']/forecast-period[@index='"+i+"']/element[@type='forecast_icon_code']/text()", bom_data)
		//logInfo("BOM data","forecast_icon_code="+forecast_icon_code)
		postUpdate("BOM_Forecast_Icon_Code_"+i, forecast_icon_code)

		var String precis = transform ("XPATH", "//forecast/area[@aac='SA_PT013']/forecast-period[@index='"+i+"']/text[@type='precis']/text()", bom_data)
		//logInfo("BOM data","precis="+precis)
		postUpdate("BOM_Precis_"+i, precis)

		val String probability_of_precipitation = transform ("XPATH", "//forecast/area[@aac='SA_PT013']/forecast-period[@index='"+i+"']/text[@type='probability_of_precipitation']/text()", bom_data)
		//logInfo("BOM data","probability_of_precipitation="+probability_of_precipitation)
		postUpdate("BOM_Precipitation_"+i, probability_of_precipitation)

		val String forecast = transform ("XPATH", "//forecast/area[@aac='SA_PW001']/forecast-period[@index='"+i+"']/text[@type='forecast']/text()", bom_data)
		//logInfo("BOM data","forecast="+forecast)
		postUpdate("BOM_Forecast_"+i, forecast)
		var String wind_range = "";
		var Pattern pattern = Pattern.compile("([0-9]+ to [0-9]+ km/h)");
		var Matcher matcher = pattern.matcher(forecast);
		if (matcher.find())
		{
    		wind_range = matcher.group(1);
		}
		else if (forecast.indexOf("Light winds")>=0)
		{
			wind_range = "Light winds"
		}
		//logInfo("BOM data","wind_range_"+i+"="+wind_range)
		postUpdate("BOM_Wind_Range_"+i, wind_range)
	}
end

rule "Get weather observation data from BOM"
when
	Time cron "0 */10 * ? * *" // update every 10 minutes
then    
	//logInfo("BOM data","reading observation data")
	val URL url = new URL("http://www.bom.gov.au/fwo/IDS60801/IDS60801.95676.json");
    val InputStreamReader instream = new InputStreamReader(url.openStream())
	var StringBuilder sb = new StringBuilder();
	var CharBuffer cb = CharBuffer.allocate(1024);

	var int read = instream.read ( cb );
	while(read != -1) {
    	sb.append(cb.array(), 0, read )
		cb.clear
		read = instream.read( cb )
	}
	instream.close();

	val String bom_data = sb.toString();	

	var String time = transform("JSONPATH", "$.observations.data[0].local_date_time", bom_data)
	time = time.substring(time.indexOf('/')+1,time.length())
	//logInfo("BOM data","observation_time="+time)
	postUpdate("BOM_Observation_Time", time)

	val air_temp = transform("JSONPATH", "$.observations.data[0].air_temp", bom_data)
	//logInfo("BOM data","air_temp="+air_temp)
	postUpdate("BOM_AirTemp", air_temp)
	val apparent_t = transform("JSONPATH", "$.observations.data[0].apparent_t", bom_data)
	//logInfo("BOM data","apparent_t="+apparent_t)
	postUpdate("BOM_ApparentTemp", apparent_t)
	val wind_dir = transform("JSONPATH", "$.observations.data[0].wind_dir", bom_data)
	//logInfo("BOM data","wind_dir="+wind_dir)
	postUpdate("BOM_WindDir", wind_dir)
	val wind_spd = transform("JSONPATH", "$.observations.data[0].wind_spd_kmh", bom_data)
	//logInfo("BOM data","wind_spd="+wind_spd)
	postUpdate("BOM_WindSpeed", wind_spd)
	val rain = transform("JSONPATH", "$.observations.data[0].rain_trace", bom_data)
	//logInfo("BOM data","rain="+rain)
	postUpdate("BOM_Rain_Amount", rain)
	val rel_hum = transform("JSONPATH", "$.observations.data[0].rel_hum", bom_data)
	//logInfo("BOM data","rel_hum="+rel_hum)
	postUpdate("BOM_Relative_Humidity", rel_hum)
	
end

No, i mean the Karaf Console. Load that up and look at your log settings

@menzy the “[rthome.model.script.actions.BusEvent] - Cannot convert” warning is related to the JSONPath and XPath Transformations. This warning is dumping the XML.

Do you have these transformations installed in the add-ons?

1 Like

Nice I didnt even see that log file! ha

Hi Guys

Thanks I was missing XPath Transformations. It is now working as expected!

@JamesC have you had any issues with this? the console reports the number fine, 26 in this case but I get this error

20:30:01.748 [WARN ] [arthome.model.script.actions.BusEvent] - Cannot convert '' to a state type which item 'BOM_Temp_Min_0' accepts: [DecimalType, QuantityType, UnDefType].

Hi guys,

I have created a binding for this. For those who are interested please go to the following link for details https://github.com/tomitan100/org.openhab.binding.bom.

To install this binding you will need to install Eclipse IoT Market add-on first under MISC in Paper UI. The binding, called “Australian BOM Weather Forecast Binding”, should then appear in Bindings page for you to install.

I have not tested all Australian states/regions/stations. Please let me know if there is any issue.

Cheers,
Tom

2 Likes

Hi Tom,

Set mine up using Terrey Hills but it seems the Observation element is throwing a stack trace.

ftp://ftp.bom.gov.au/anon/gen/fwo/IDN60920.xml
Weather station ID : 94759

2019-02-14 16:31:32.886 [INFO ] [nhab.binding.bom.internal.BomHandler] - Processing forecast data from FTP path: ftp://ftp.bom.gov.au/anon/gen/fwo/IDN10064.xml, area ID: NSW_PT139
2019-02-14 16:31:33.595 [INFO ] [nhab.binding.bom.internal.BomHandler] - Completed processing forecast data.
2019-02-14 16:31:34.445 [WARN ] [mmon.WrappedScheduledExecutorService] - Scheduled runnable ended with an exception:
java.lang.NumberFormatException: null
at java.math.BigDecimal.(BigDecimal.java:494) ~[?:?]
at java.math.BigDecimal.(BigDecimal.java:383) ~[?:?]
at java.math.BigDecimal.(BigDecimal.java:806) ~[?:?]
at java.math.BigDecimal.valueOf(BigDecimal.java:1274) ~[?:?]
at org.eclipse.smarthome.core.library.types.DecimalType.(DecimalType.java:53) ~[?:?]
at org.openhab.binding.bom.internal.BomHandler.updateChannelState(BomHandler.java:351) ~[?:?]
at org.openhab.binding.bom.internal.BomHandler.lambda$2(BomHandler.java:164) ~[?:?]
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382) ~[?:?]
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580) ~[?:?]
at org.openhab.binding.bom.internal.BomHandler.refreshObservation(BomHandler.java:146) ~[?:?]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:?]
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) ~[?:?]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) ~[?:?]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) ~[?:?]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:?]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:?]
at java.lang.Thread.run(Thread.java:748) [?:?]

If I use the first station defined in the file (94768) it works, similar to your Perth example, so not sure if it’s the values from my station or the fact it’s further down the file.

Regards,
Nick

Hi Nick,

I have fixed this. Your weather station does not have atmospheric pressure data and the code was not handling the exception correctly. Also there seems to be very limited forecast data for the area you chose. I will confirm this comparing with BOM site later today.

Please uninstall and then reinstall. You might have to remove and re-add your thing, and possibly restart.

Regards,
Tom

Hi Nick,

I think you want to use ftp://ftp.bom.gov.au/anon/gen/fwo/IDN11060.xml for the forecast instead. You will get 8 days of forecasts but there is one slight problem I see. You will not get the forecast texts as they are in IDN10064. I will have to work out how the XML is referenced.

Regards,
Tom

Ahh I see, when I saw the limited data, I assumed it derived it from the parent-aac but looking at the normal bom website, at the bottom is says : Product derived from IDN11060 and IDN10064