Getting the current UV index and UV Protection time for Australia

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

1 Like