Hi, the OpenUV - UV Index Forecast API (former UV Index API) has been recently relaunched and available for public access.
I am currently developing a new setup with the new API. I have it working QAD. Once I have a nice configuration, I will update this post.
Hi folks, @rtvb
any update about this configuration? Iâm trying to collect all the info via curl then, using sed, trying to take the values I need. But maybe you are doing a better job
Please let us know
thanks
Andrea
I have been playing a lot with Home Assistant lately, so the migration has not yet been completed. Please find below a working (partial) update.
http.cfg
# Set up the http binding to fetch the data once every 15 minutes. updateInterval=15*60*1000=900.000
openuv_uv.url = https://api.openuv.io/api/v1/uv?lat=51.0&lng=4.0{x-access-token=redacted}
openuv_uv.updateInterval = 720000
openuv_forecast.url = https://api.openuv.io/api/v1/forecast?lat=51.0&lng=4.0{x-access-token=redacted}
openuv_forecast.updateInterval = 720000
openuv_protection.url = https://api.openuv.io/api/v1/protection?lat=51.0&lng=4.0{x-access-token=redacted}
openuv_protection.updateInterval = 720000
openuv_exposure.url = https://api.openuv.io/api/v1/exposure?lat=51.0&lng=4.0{x-access-token=redacted}
openuv_exposure.updateInterval = 720000
uvi.items
// =========================================================================================
// UV Index
// =========================================================================================
// https://www.openuv.io/console
Group gUvi "UV Index" (gWeather)
// get raw json every 10 minutes
// use http caching to prevent hitting the API too much :-)
// String Uvi_Raw (gUvi) // { http="<[uvimateCache:600000:REGEX((.*))]" }
String Uvi_Uv_Json (gUvi) { http="<[openuv_uv:180000:REGEX((.*))]" } // every 3 minutes
String Uvi_Forecast_Json (gUvi) { http="<[openuv_uv:180000:REGEX((.*))]" } // every 3 minutes
String Uvi_Protection_Json (gUvi) { http="<[openuv_uv:180000:REGEX((.*))]" } // every 3 minutes
String Uvi_Exposure_Json (gUvi) { http="<[openuv_uv:180000:REGEX((.*))]" } // every 3 minutes
// these items are populated using a rule
Number Uvi_Uv "Huidige UV Index [%.2f]" <line> (gUvi, gChart)
DateTime Uvi_Uv_Time "Waarneming [%1$tH:%1$tM]" <clock> (gUvi)
Number Uvi_Uv_Max "Max. UV-ndex vandaag verwacht [%.2f]" <line> (gUvi)
DateTime Uvi_Uv_Max_Time "Tijdstip max. UV-index [%1$tH:%1$tM]" <clock> (gUvi)
String Uvi_Risk "Risico UV-straling [MAP(uvi_nl.map):%s]" <text> (gUvi)
DateTime Uvi_Protection_From "Begin bescherming vandaag [%1$tH:%1$tM]" <clock> (gUvi)
DateTime Uvi_Protection_To "Einde bescherming vandaag [%1$tH:%1$tM]" <clock> (gUvi)
DateTime Uvi_LastUpdate "Bijgewerkt [%1$tH:%1$tM]" <clock> (gUvi, gLastUpdated)
uvi.rules
rule UvimateUpdated
when
Item Uvi_Uv_Json received update or
Item Uvi_Forecast_Json received update or
Item Uvi_Protection_Json received update or
Item Uvi_Exposure_Json received update or
System started
then
logDebug(logger, "Uvimate received update")
// asap
Uvi_LastUpdate.postUpdate(new DateTimeType)
// get values
val String raw_uv = Uvi_Uv_Json.state.toString
val uv = Float.parseFloat(transform("JSONPATH", "$.result.uv", raw_uv))
val uv_max = Float.parseFloat(transform("JSONPATH", "$.result.uv_max", raw_uv))
// directly converting to DateTimeType does not respect the timezone, DateTime does.
val DateTime uv_time = new DateTime(transform("JSONPATH", "$.result.uv_time", raw_uv))
val DateTime uv_max_time = new DateTime(transform("JSONPATH", "$.result.uv_max_time", raw_uv))
// debug
logDebug(logger, "raw_uv : " + raw_uv)
logDebug(logger, "uvi : " + uv)
logDebug(logger, "uvi time : " + uv_time)
logDebug(logger, "uviMax : " + uv_max)
logDebug(logger, "uviMaxTime : " + uv_max_time)
logDebug(logger, "***")
var risk = 'UNKNOWN'
if (uv < 3.0) {
risk = "LOW"
logDebug(logger, risk)
} else if (uv < 6.0) {
risk = 'MODERATE'
} else if (uv < 8.0) {
risk = 'HIGH'
} else if (uv < 11.0) {
risk = 'VERY_HIGH'
} else {
risk = 'EXTREME'
}
logDebug(logger, "Risk : " + risk)
// post updates
Uvi_Uv.postUpdate( uv.toString ) // uv
Uvi_Uv_Max.postUpdate( uv_max.toString ) // uv_max
Uvi_Uv_Time.postUpdate(uv_time.toString)
Uvi_Uv_Max_Time.postUpdate(uv_max_time.toString)
Uvi_Risk.postUpdate(risk)
end
Just because I saw it: You have to typos in your rule:
Item Uvi_Protection_Jason received update or
Item Uvi_Exposure_Jason received update or
should be
Item Uvi_Protection_Json received update or
Item Uvi_Exposure_Json received update or
donât you think so?
Youâre right. Iâve edited my code.
Are you sure this is working now? how can you send the API key via url?
In the meantime Iâve found another way to access their data, using a script to collect the data form their website, and using the http binding and jsonpath from internal openhab web server:
the script openuv.sh
#!/bin/sh
/usr/bin/curl -s -XGET 'https://api.openuv.io/api/v1/uv?lat=MYLAT&lng=MYLNG' -H "x-access-token: MYAPIKEY" > /etc/openhab2/html/openuv.txt
the rule
rule openuv
when
Time cron "* 0/15 * * * ?" // this one cycles every 15 minutes.
then
// executing the script and waiting for the JSON return
var String cmd = "sh /etc/openhab2/myscripts/openuv.sh"
executeCommandLine(cmd, 120000)
end
items
String Http_Openuv_UVIndex "UV Index (now): [%s]" (gOutdoor, gWeather) { http="<[http://localhost:8080/static/openuv.txt:60000:JSONPATH($.result.uv)]" }
String Http_Openuv_UVIndexMax "UV Index (max): [%s]" (gOutdoor, gWeather) { http="<[http://localhost:8080/static/openuv.txt:60000:JSONPATH($.result.uv_max)]" }
âŠ
Apologies
Now it should be better
Bene
I use the http binding; this is the config. That syntax is required to send headers.
This way you donât need to executeCommandLine.
Please also read the OP. My last example isnât a complete solution but a WIP update to it.
Hi,
thanks for your input. I modified your rule to fit it to my needs, but for some reason it is causing havoc on my openhab installation (running on 2.3.0~20180324205302-1 (Build #1240)).
When loading this rule during startup, the boot process is stopped.
Any help on why and what to do to fix it? Never had this before
rule "openuv"
when
Time cron "0 0/15 * 1/1 * ? *" // this one cycles every 15 minutes.
then
executeCommandLine("sh /srv/openhab2-conf/scripts/openuv.sh", 10000)
end
rule "UV recalc"
when
Item Openuv_sunburn received update or
Time cron "0 0/16 * 1/1 * ? *"
then
var int hours = ((Openuv_sunburn.state as DecimalType).intValue / 60) - (24 * days)
var int minutes = ((Openuv_sunburn.state as DecimalType).intValue - 60 * (24 * days + hours))
var String result = ""
// STUNDEN
if (hours > 0) {
result = result + hours + " Std. / "
}
// MINUTEN
if (minutes > 0) {
result = result + minutes + " Min."
} Openuv_sunburn_format.postUpdate(result)
logInfo("UV recalc", "Sonnenbrandzeit upgedated auf: " + Openuv_sunburn_format.state)
end
The Shellscript is as below:
#!/bin/sh
curl -X GET 'https://api.openuv.io/api/v1/uv?lat=xx.xx&lng=xx.xx&alt=xx' -H 'x-access-token: mytoken' > /srv/openhab2-conf/html/openuv.txt
The items are defined the following way:
String Openuv_UVIndex "UV Index (Jetzt): [%s]" <uvsun> (Wetter) { http="<[http://192.x.xx.x:8080/static/openuv.txt:60000:JSONPATH($.result.uv)]" }
String Openuv_UVIndexMax "UV Index (max): [%s]" <uvsun> (Wetter) { http="<[http://192.x.xx.x:8080/static/openuv.txt:60000:JSONPATH($.result.uv_max)]" }
String Openuv_Ozone "Ozone Index (Jetzt): [%s]" <ozon> (Wetter) { http="<[http://192.x.xx.x:8080/static/openuv.txt:60000:JSONPATH($.result.ozone)]" }
Number Openuv_sunburn "Sonnenbrand in Minuten:[%s] " <sunburn> (Wetter) { http="<[http://192.x.xx.x:8080/static/openuv.txt:60000:JSONPATH($.result.safe_exposure_time.st3)]" }
Number Openuv_sunburn_format "Sonnenbrand in: [%s] %unit%" <sunburn> (Wetter)
Whenever I exclude the rule (rename the rules file, so it wonât get loaded) the OpenHAB service is starting up as normal.
thanks upfront for any help on this matter!
Kurt
can you please check permissions of this file?
thanks
Andrea
i find this very interesting - as my whole Family is outside quite often for biking, running or whatever!
I just did @rtvb already suggested an simple http binding with the additional header. With that you wonât need all that external script stuff⊠the API gets updated every 3-4 hours, as I read. you have something like 500 API-calls per day, so I figured and update every hour is enough. 1 hour in msec is 3600000.
insert a cached URL in http.cfg
# configuration of the openuv.io cache item
openUV.url= https://api.openuv.io/api/v1/uv?lat=<<LAT>>&lng=<<LNG>>{x-access-token=<<API-KEY>>}
openUV.updateInterval=3600000
please replac LAT und LNG with your Location and replace the API-Key
with that cached item (itâs a string in JSON format), you can then easily update your items:
Number openUV_UV "aktueller UV-Wert [%d]" { http="<[openUV:60000:JSONPATH($.result.uv)]" }
DateTime openUV_UV_Time "UV-Wert Messung [%1$tH:%1$tM]" { http="<[openUV:60000:JSONPATH($.result.uv_time)]" }
Number openUV_UV_Max "Maximaler UV-Wert [%d]" { http="<[openUV:60000:JSONPATH($.result.uv_max)]" }
DateTime openUV_UV_MaxTime "Max. UV-Wert Zeit [%1$tH:%1$tM]" { http="<[openUV:60000:JSONPATH($.result.uv_max_time)]" }
Number openUV_Ozon "Ozonwert [%d]" { http="<[openUV:60000:JSONPATH($.result.ozone)]" }
Number openUV_st1 "maximale zeit Hauttyp 1 [%d min]" { http="<[openUV:60000:JSONPATH($.result.safe_exposure_time.st1)]" }
Number openUV_st2 "maximale zeit Hauttyp 3 [%d min]" { http="<[openUV:60000:JSONPATH($.result.safe_exposure_time.st2)]" }
Number openUV_st3 "maximale zeit Hauttyp 4 [%d min]" { http="<[openUV:60000:JSONPATH($.result.safe_exposure_time.st3)]" }
Number openUV_st4 "maximale zeit Hauttyp 5 [%d min]" { http="<[openUV:60000:JSONPATH($.result.safe_exposure_time.st4)]" }
Number openUV_st5 "maximale zeit Hauttyp 6 [%d min]" { http="<[openUV:60000:JSONPATH($.result.safe_exposure_time.st5)]" }
Number openUV_st6 "maximale zeit Hauttyp 7 [%d min]" { http="<[openUV:60000:JSONPATH($.result.safe_exposure_time.st6)]" }
Thatâs it! of Course you can now add some additional items, which calculate the risk (e.g. for high Ozone-values or high UV-values!) and so on. But getting the raw items is easy as that! even DateTime works easily.
Hi,
aha, interesting. Itâs owned by openhabian:openhabian (obviously, this is what Iâm running here ). Iâve now made it openhab:openhabian. Thanks for the hint.
Any idea why openhab would completely freeze at startup due to it?
Kurt
Very nice! Thanks for sharing!
Kurt
Thank @binderth
just consider the sunburn items (st1, 2 âŠ) are in minutes, not in seconds
But thanks for your example, it works nicely.
thanks
Andrea
youâre so right. I updated the code in my post above so it will be correctly displayed in UI.
All-
I am trying to get this to work, and I keep getting the error:
2018-04-05 23:03:33.412 [ERROR] [org.openhab.io.net.http.HttpUtil ] - Fatal transport error: javax.net.ssl.SSLHandshakeException: sun.security.validator.$
2018-04-05 23:03:33.416 [ERROR] [ab.binding.http.internal.HttpBinding] - No response received from âopenUVâ
I have the following lines in http.cfg:
openUV.url=https://api.openuv.io/api/v1/uv?lat=41.3&lng=-72.2{x-access-token=redacted}
openUV.updateInterval=3600000
What am I doing wrong?
Many thanks,
-Mark
Whatâs your system specs? openHABian?
Try in the shell:
curl -s -XGET 'https://api.openuv.io/api/v1/uv?lat=41.3&lng=-72.2' -H "x-access-token: <<APIKEY>>"
Whatâs the outcome?