The Smart Weather Station Tile App under more and Convenience.
What products work with this that I can attach? Does this pull information from a PWS device such as the ones that work with wunderground?
The Smart Weather Station Tile App under more and Convenience.
What products work with this that I can attach? Does this pull information from a PWS device such as the ones that work with wunderground?
It pulls data from the wunderground API. So if your PWS is hooked up to wunderground, you can get data from it. Davis Weather Station
Sorry its a Monday in my head⌠one quick clarification I would need my own PWS and I canât just use either the API I have with Wunderground without my own personal station. IE I canât connect to a neighbors unit.
When I open the app is says Device to connect too but no box to enter any API data.
Thank you
The Smart Weather Station Controller app just updates devices you have added to your account. I believe to add the actual device, you need to use the web ide (http://ide.smartthings.com) and add the Smart Weather Station Tile. Thatâs also where you put in your location data.
It doesnât have to be a PWS you control. You should be able to use any location info the wunderground API can understand.
Everything works perfect now thank you so much Dianaga.
Installed the device in the IDE as Smart Weather Tile Device set network id to Wunderground API and Zip code to the Station I wanted to use and after 5 min voila all is perfect!
Vert insterested in the is app but cannot figure out where to get the smart weather tile app to add in my developer account. Could i get a few more walk through steps?
That should give you a functioning weather tile.
Fantastic! worked great. 1 last question, where can i put the PWS variable to include my own station?
Weather Tile Device click on it then preferences, Zip Code worked for me 3rd from the bottom.
This one should display wind direction for you
/**
* SmartWeather Station v2
*
* Author: SmartThings
*
* Date: 2014-10-29
*/
// for the UI
metadata {
// Automatically generated. Make future change here.
definition (name: "SmartWeather Station Tile v2", namespace: "smartthings", author: "SmartThings") {
capability "Illuminance Measurement"
capability "Temperature Measurement"
capability "Relative Humidity Measurement"
capability "polling"
attribute "localSunrise", "string"
attribute "localSunset", "string"
attribute "city", "string"
attribute "timeZoneOffset", "string"
attribute "weather", "string"
attribute "wind", "string"
attribute "windDir", "string"
attribute "weatherIcon", "string"
attribute "forecastIcon", "string"
attribute "feelsLike", "string"
attribute "percentPrecip", "string"
attribute "alert", "string"
attribute "alertKeys", "string"
attribute "sunriseDate", "string"
attribute "sunsetDate", "string"
command "refresh"
}
preferences {
input "zipCode", "text", title: "Zip Code (optional)", required: false
}
tiles {
valueTile("temperature", "device.temperature") {
state "default", label:'${currentValue}°',
backgroundColors:[
[value: 19, color: "#9F8ACD"],
[value: 31, color: "#153591"],
[value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"],
[value: 74, color: "#44b621"],
[value: 84, color: "#f1d801"],
[value: 95, color: "#d04e00"],
[value: 96, color: "#bc2323"]
]
}
valueTile("humidity", "device.humidity", decoration: "flat") {
state "default", label:'${currentValue}% humidity'
}
standardTile("weatherIcon", "device.weatherIcon", decoration: "flat") {
state "chanceflurries", icon:"st.custom.wu1.chanceflurries", label: ""
state "chancerain", icon:"st.custom.wu1.chancerain", label: ""
state "chancesleet", icon:"st.custom.wu1.chancesleet", label: ""
state "chancesnow", icon:"st.custom.wu1.chancesnow", label: ""
state "chancetstorms", icon:"st.custom.wu1.chancetstorms", label: ""
state "clear", icon:"st.custom.wu1.clear", label: ""
state "cloudy", icon:"st.custom.wu1.cloudy", label: ""
state "flurries", icon:"st.custom.wu1.flurries", label: ""
state "fog", icon:"st.custom.wu1.fog", label: ""
state "hazy", icon:"st.custom.wu1.hazy", label: ""
state "mostlycloudy", icon:"st.custom.wu1.mostlycloudy", label: ""
state "mostlysunny", icon:"st.custom.wu1.mostlysunny", label: ""
state "partlycloudy", icon:"st.custom.wu1.partlycloudy", label: ""
state "partlysunny", icon:"st.custom.wu1.partlysunny", label: ""
state "rain", icon:"st.custom.wu1.rain", label: ""
state "sleet", icon:"st.custom.wu1.sleet", label: ""
state "snow", icon:"st.custom.wu1.snow", label: ""
state "sunny", icon:"st.custom.wu1.sunny", label: ""
state "tstorms", icon:"st.custom.wu1.tstorms", label: ""
state "cloudy", icon:"st.custom.wu1.cloudy", label: ""
state "partlycloudy", icon:"st.custom.wu1.partlycloudy", label: ""
state "nt_chanceflurries", icon:"st.custom.wu1.nt_chanceflurries", label: ""
state "nt_chancerain", icon:"st.custom.wu1.nt_chancerain", label: ""
state "nt_chancesleet", icon:"st.custom.wu1.nt_chancesleet", label: ""
state "nt_chancesnow", icon:"st.custom.wu1.nt_chancesnow", label: ""
state "nt_chancetstorms", icon:"st.custom.wu1.nt_chancetstorms", label: ""
state "nt_clear", icon:"st.custom.wu1.nt_clear", label: ""
state "nt_cloudy", icon:"st.custom.wu1.nt_cloudy", label: ""
state "nt_flurries", icon:"st.custom.wu1.nt_flurries", label: ""
state "nt_fog", icon:"st.custom.wu1.nt_fog", label: ""
state "nt_hazy", icon:"st.custom.wu1.nt_hazy", label: ""
state "nt_mostlycloudy", icon:"st.custom.wu1.nt_mostlycloudy", label: ""
state "nt_mostlysunny", icon:"st.custom.wu1.nt_mostlysunny", label: ""
state "nt_partlycloudy", icon:"st.custom.wu1.nt_partlycloudy", label: ""
state "nt_partlysunny", icon:"st.custom.wu1.nt_partlysunny", label: ""
state "nt_sleet", icon:"st.custom.wu1.nt_sleet", label: ""
state "nt_rain", icon:"st.custom.wu1.nt_rain", label: ""
state "nt_sleet", icon:"st.custom.wu1.nt_sleet", label: ""
state "nt_snow", icon:"st.custom.wu1.nt_snow", label: ""
state "nt_sunny", icon:"st.custom.wu1.nt_sunny", label: ""
state "nt_tstorms", icon:"st.custom.wu1.nt_tstorms", label: ""
state "nt_cloudy", icon:"st.custom.wu1.nt_cloudy", label: ""
state "nt_partlycloudy", icon:"st.custom.wu1.nt_partlycloudy", label: ""
}
valueTile("feelsLike", "device.feelsLike", decoration: "flat") {
state "default", label:'feels like ${currentValue}°'
}
valueTile("wind", "device.wind", decoration: "flat") {
state "default", label:'wind ${currentValue} mph'
}
valueTile("windDir", "device.windDir", decoration: "flat") {
state "default", label:'${currentValue}'
}
valueTile("weather", "device.weather", decoration: "flat") {
state "default", label:'${currentValue}'
}
valueTile("city", "device.city", decoration: "flat") {
state "default", label:'${currentValue}'
}
valueTile("percentPrecip", "device.percentPrecip", decoration: "flat") {
state "default", label:'${currentValue}% precip'
}
standardTile("refresh", "device.weather", decoration: "flat") {
state "default", label: "", action: "refresh", icon:"st.secondary.refresh"
}
valueTile("alert", "device.alert", width: 3, height: 1, decoration: "flat") {
state "default", label:'${currentValue}'
}
valueTile("rise", "device.localSunrise", decoration: "flat") {
state "default", label:'${currentValue}'
}
valueTile("set", "device.localSunset", decoration: "flat") {
state "default", label:'${currentValue}'
}
valueTile("light", "device.illuminance", decoration: "flat") {
state "default", label:'${currentValue} lux'
}
main(["temperature", "weatherIcon","feelsLike"])
details(["temperature", "weatherIcon","feelsLike","wind","windDir","weather", "city","percentPrecip", "refresh","alert", "humidity","rise","set","light"])}
}
// parse events into attributes
def parse(String description) {
log.debug "Parsing '${description}'"
}
// handle commands
def poll() {
log.debug "Executing 'poll', location: ${location.name}"
// Current conditions
def obs = get("conditions")?.current_observation
if (obs) {
def weatherIcon = obs.icon_url.split("/")[-1].split("\\.")[0]
if(getTemperatureScale() == "C") {
send(name: "temperature", value: Math.round(obs.temp_c), unit: "C")
send(name: "feelsLike", value: Math.round(obs.feelslike_c as Double), unit: "C")
} else {
send(name: "temperature", value: Math.round(obs.temp_f), unit: "F")
send(name: "feelsLike", value: Math.round(obs.feelslike_f as Double), unit: "F")
}
send(name: "humidity", value: obs.relative_humidity[0..-2] as Integer, unit: "%")
send(name: "weather", value: obs.weather)
send(name: "windDir", value: obs.wind_dir)
send(name: "weatherIcon", value: weatherIcon, displayed: false)
send(name: "wind", value: Math.round(obs.wind_mph) as String, unit: "MPH") // as String because of bug in determining state change of 0 numbers
if (obs.local_tz_offset != device.currentValue("timeZoneOffset")) {
send(name: "timeZoneOffset", value: obs.local_tz_offset, isStateChange: true)
}
def cityValue = "${obs.display_location.city}, ${obs.display_location.state}"
if (cityValue != device.currentValue("city")) {
send(name: "city", value: cityValue, isStateChange: true)
}
// Sunrise / sunset
def a = get("astronomy")?.moon_phase
def today = localDate("GMT${obs.local_tz_offset}")
def ltf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm")
ltf.setTimeZone(TimeZone.getTimeZone("GMT${obs.local_tz_offset}"))
def utf = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
utf.setTimeZone(TimeZone.getTimeZone("GMT"))
def sunriseDate = ltf.parse("${today} ${a.sunrise.hour}:${a.sunrise.minute}")
def sunsetDate = ltf.parse("${today} ${a.sunset.hour}:${a.sunset.minute}")
def tf = new java.text.SimpleDateFormat("h:mm a")
tf.setTimeZone(TimeZone.getTimeZone("GMT${obs.local_tz_offset}"))
def localSunrise = "${tf.format(sunriseDate)}"
def localSunset = "${tf.format(sunsetDate)}"
send(name: "localSunrise", value: localSunrise, descriptionText: "Sunrise today is at $localSunrise")
send(name: "localSunset", value: localSunset, descriptionText: "Sunset today at is $localSunset")
send(name: "illuminance", value: estimateLux(sunriseDate, sunsetDate, weatherIcon))
// Forecast
def f = get("forecast")
def f1= f?.forecast?.simpleforecast?.forecastday
if (f1) {
def icon = f1[0].icon_url.split("/")[-1].split("\\.")[0]
def value = f1[0].pop as String // as String because of bug in determining state change of 0 numbers
send(name: "percentPrecip", value: value, unit: "%")
send(name: "forecastIcon", value: icon, displayed: false)
}
else {
log.warn "Forecast not found"
}
// Alerts
def alerts = get("alerts")?.alerts
def newKeys = alerts?.collect{it.type + it.date_epoch} ?: []
log.debug "WUSTATION: newKeys: $newKeys"
log.trace device.currentState("alertKeys")
def oldKeys = device.currentState("alertKeys")?.jsonValue
log.debug "WUSTATION: oldKeys: $oldKeys"
def noneString = "no current weather alerts"
if (!newKeys && oldKeys == null) {
send(name: "alertKeys", value: newKeys.encodeAsJSON(), displayed: false)
send(name: "alert", value: noneString, descriptionText: "${device.displayName} has no current weather alerts", isStateChange: true)
}
else if (newKeys != oldKeys) {
if (oldKeys == null) {
oldKeys = []
}
send(name: "alertKeys", value: newKeys.encodeAsJSON(), displayed: false)
def newAlerts = false
alerts.each {alert ->
if (!oldKeys.contains(alert.type + alert.date_epoch)) {
def msg = "${alert.description} from ${alert.date} until ${alert.expires}"
send(name: "alert", value: pad(alert.description), descriptionText: msg, isStateChange: true)
newAlerts = true
}
}
if (!newAlerts && device.currentValue("alert") != noneString) {
send(name: "alert", value: noneString, descriptionText: "${device.displayName} has no current weather alerts", isStateChange: true)
}
}
}
else {
log.warn "No response from Weather Underground API"
}
}
def refresh() {
poll()
}
def configure() {
poll()
}
private pad(String s, size = 25) {
def n = (size - s.size()) / 2
if (n > 0) {
def sb = ""
n.times {sb += " "}
sb += s
n.times {sb += " "}
return sb
}
else {
return s
}
}
private get(feature) {
getWeatherFeature(feature, zipCode)
}
private localDate(timeZone) {
def df = new java.text.SimpleDateFormat("yyyy-MM-dd")
df.setTimeZone(TimeZone.getTimeZone(timeZone))
df.format(new Date())
}
private send(map) {
log.debug "WUSTATION: event: $map"
sendEvent(map)
}
private estimateLux(sunriseDate, sunsetDate, weatherIcon) {
def lux = 0
def now = new Date().time
if (now > sunriseDate.time && now < sunsetDate.time) {
//day
switch(weatherIcon) {
case 'tstorms':
lux = 200
break
case ['cloudy', 'fog', 'rain', 'sleet', 'snow', 'flurries',
'chanceflurries', 'chancerain', 'chancesleet',
'chancesnow', 'chancetstorms']:
lux = 1000
break
case 'mostlycloudy':
lux = 2500
break
case ['partlysunny', 'partlycloudy', 'hazy']:
lux = 7500
break
default:
//sunny, clear
lux = 10000
}
//adjust for dusk/dawn
def afterSunrise = now - sunriseDate.time
def beforeSunset = sunsetDate.time - now
def oneHour = 1000 * 60 * 60
if(afterSunrise < oneHour) {
//dawn
lux = (long)(lux * (afterSunrise/oneHour))
} else if (beforeSunset < oneHour) {
//dusk
lux = (long)(lux * (beforeSunset/oneHour))
}
}
else {
//night - always set to 10 for now
//could do calculations for dusk/dawn too
lux = 10
}
lux
}
Whenever this is called on stock weather device
device?.supportedAttributes
This error is thrown:
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object âtemperatureâ with class âphysicalgraph.device.cache.AttributeDTOâ to class âphysicalgraph.device.Attributeâ
Anyone knows whatâs up with this?
@nelemansc
Thank you very much! You should submit this revision to ST! @mager
Did you just have to add a line or two to the old SmartWeather Station Tile code? I see the attribute âwindDirâ, âstringâ line. I donât know anything about code but maybe I can learn a little.
What is the easiest way to replace my current code? I have added / updated code before when it was listed under âMy SmartAppsâ in the IDE but the SmartWeather Station Tile is not listed under âMy SmartAppsâ itâs under âMy Devicesâ. I also use the SmartWeather Station Controller of course.
Under âMy Devicesâ can I use the EDIT button to get to the old code? Or do I need to use the DELETE button and do away with that device and enter this new code in âMy SmartAppsâ (donât think this would work with my ActiON Dashboard).
I use ActiON Dashboard which shows this weather, maybe in the future it will show the wind.
Thanks!
Yup, just had to add a few lines to reference the wind direction condition from Weather Underground API and also to add an additional tile http://www.wunderground.com/weather/api/d/docs?d=data/conditions&MR=1
As you can see on that page listed above, you could theoretically create tiles for all kinds of condition information for wind_degrees, wind_gust_mph, solarradiation, UV, etc.
Go into My Device Types in the IDE and select New SmartDevice in the upper right corner.
Then select the âFrom Codeâ option on the New SmartDevice screen
Copy/paste the code from above and click Create at the bottom of the screen. (The create process takes 20-30 seconds, so donât be alarmed if it looks like the page is frozen.)
On the next screen that loads, select âPublishâ, then âFor Meâ.
This created a new custom device type that you will then assign to a specific device. Now go to My Devices in the IDE and find your current SmartWeather Tile. Click on it, then click Edit and change the Type to SmartWeather Tile v2 (located towards the bottom of the list).
Click Update, then refresh the SmartWeather Tile in the SmartThings app. It should populate the new wind direction value on a new tile. If not, force close the SmartThings app and reopen.
@nelemansc
Cassidy,
Thank you very much and very cool, this helps a lot. Iâm surprised it had to be another tile, I thought it would be the same tile as the wind speed. It bumped my humidity tile down to the next page, not a big deal. I tried to tap and hold a tile to rearrange but it does not allow it. I was going to bring the humidity tile back up and drop the âfeels like _â down.
If anyone wants to see the change:
And lower page:
Thank you!
@Dave no problem, glad I could help!
I actually rearranged the tiles in the custom device type due to personal preference, but you could do the same with yours to put the tiles in whatever order you like. Go back into the SmartWeather Tile v2 device in My Device Types and edit line 149-
details(["temperature", "weatherIcon","feelsLike","wind","windDir","weather", "city","percentPrecip", "refresh","alert", "humidity","rise","set","light"])}
Whatever order you put the tile names in is the order of how they are displayed in the device. So replace your line 149 with the following-
details(["temperature", "weatherIcon","humidity","wind","windDir","weather", "city","percentPrecip", "refresh","alert","feelsLike","rise","set","light"])}
Sweet! I would like to learn this stuff and you did just teach me some! I owe U a beer!
@nelemansc
I was able to update the order of my tiles. I ended up dropping the city down and bringing the humidity up. I figured itâs always going to be the same city so no need to always see it. If I watch the IDE Log is there anyway to get the PWS ID? Iâm pretty sure I know which PWS is being used but wanted to verify if easy.
Thanks!
This is cool, wish this was a default installed app.
Do you know what that yellow circle on the corner indicates @Dianoga? I can only select one at a time.
This code doesnât work anymore
Error
No signature of method: script14148161440891502062458.metadata() is applicable for argument types: (script14148161440891502062458$_run_closure1) values: [script14148161440891502062458$_run_closure1@3316d9b7] Possible solutions: getMetadata(), getState(), setState(java.lang.Object), metaClass(groovy.lang.Closure)
The yellow circle denotes which of the âsub-tilesâ will appear as the main tile for the device in the higher level menu/page.
Thanks. Do you know why it doesnât update the information automatically? I need to manually go in and refresh it every few hours.