This script is implemented in JRuby, my favourite scripting language, due to its elegance and simplicity.
Note I have an item called Sun_Elevation that I use in many places. It’s linked to the astro binding.
To use this for your location:
- Open https://uvdata.arpansa.gov.au/xml/uvvalues.xml and find your location id and use it in the script
- Find out the BOM file and area code for your area. It’s a bit tricky - if someone can explain how to do this, I’d appreciate it.
uv.items
Number UV_Index "UV Index [%.1f]" <sun_clouds>
String UV_Protection "UV Protection" <shield>
uv.rb
require 'openhab'
require 'rexml/document' # for xml parsing
require 'net/ftp' # for BOM data dowload
def arpansa_uv(location_id)
url = 'https://uvdata.arpansa.gov.au/xml/uvvalues.xml'
xml_string = HTTP.sendHttpGetRequest(url)
xml = REXML::Document.new xml_string
xml.root.elements["location[@id='#{location_id}']/index]"]&.text.to_f
end
def bom_download(filename)
ftp = Net::FTP.new('ftp2.bom.gov.au')
ftp.login
ftp.chdir('/anon/gen/fwo')
ftp.gettextfile(filename, nil)
end
def bom_uv_time(filename, aac)
xml = REXML::Document.new bom_download(filename)
xml.root.elements["forecast/area[@aac='#{aac}']"]&.each_element do |forecast_period|
uv_alert = forecast_period.elements["text[@type='uv_alert']"]
return uv_alert.text.match(/Sun protection ([^ ]+ to [^ ,]+),/)[1] unless uv_alert.nil?
end
end
rule 'UV: Fetch UV Data' do
every 5.minutes
only_if { Sun_Elevation.zero? || Sun_Elevation.positive? }
run { UV_Index.update arpansa_uv('Gold Coast') }
end
rule 'UV: Zero out after sunset' do
channel 'astro:sun:home:set#event'
run { UV_Index.update 0 }
end
rule 'UV: Get Protection Time' do
every :day, at: '5am'
every :day, at: '7am'
on_start
run { UV_Protection.update bom_uv_time('IDQ10610.xml', 'QLD_ME003') }
end
I used to use openuv but their rate limiting is… well, limiting.
The BOM’s UV protection time will return a string such as 8:10am to 2:50pm