Ok, the script is working...for now. I'm not sure if it will break this evening.
I think what they are doing is swapping the order in which max and min temp data is being delivered. For instance, when the first entry is "This Afternoon", maximum temperature data has a layout key of k-p24-n[X entries]-1. At some point, "This Afternoon" rolls out of the forecast and then you are left with "Tonight" as the most current temperature forecast. When this happens, the maximum temperature data layout key turns into k-p24-n[X entries]-2 and the minimum temperature data layout key becomes k-p24-n[X entries]-1 (the final digit in the key appears to give the order that things are supposed to be displayed). It took a bit more code, but I am keeping maximum and minimum data seperate and keeping track of the order they're supposed to be displayed in (as indicated by the key). I'll have to see precisely how this works tonight.
Next up, I need to make a dictionary to convert the weather summary that is delivered into a standardized weather number that corresponds to the weather .png images most of us use.
Added script for you to look at . It's not ready to plug into HB just yet, but you can follow the code:
Code: Select all
'==========================================================================================================================
' Title: Yahoo Weather Device
' Author: Osler
' Language: VBScript
' Description: A script to gather weather data from the Yahoo RSS feed. Provides current weather conditions and a 1 day
' forecast. WeatherNumber and ForecastWeatherNumber correspond to one of the included .gif files to provide an image
' representation of the current or forecasted weather. All images are from Yahoo's website. Please see the terms and
' conditions of using the YahooWeather RSS feed at http://developer.yahoo.com/weather/
' Device Name: CurrentWeather
' Properties: CWZipCode (should be populated with your 5-digit zipcode prior to running script)
' CWUnits (should be populated with either f for Farenheight or c for Celsius prior to running script)
' CWWindChill
' CWWindSpeed
' CWWindDirection
' CWHumidity
' CWBarometer
' CWRising
' CWWeather
' CWTemperature
' CWLocation
' CWTime
' CWWeatherNumber
' CWDay
' CWDate
' CWHigh
' CWLow
' CWForecastDay
' CWForecastDate
' CWForecastLow
' CWForecastHigh
' CWForecastWeather
' CWForecastWeatherNumber
'==========================================================================================================================
'On Error Resume Next
Dim XMLHTTP
Dim YahooURL, NOAAURL
Dim ZipCode
Dim Units
Dim I, D, N, P
Dim YahooXML, NOAAXML
Dim xmlData
Dim City, State, Country
Dim Units_Temp, Units_Dist, Units_Pres, Units_Spd
Dim WindChill, WindDirection, WindSpeed
Dim Humidity, Visibility, Pressure, Rising
Dim Sunrise, Sunset
Dim LayoutKey(1)
Dim Latitude, Longitude
Dim Condition, Code, Temperature, LastUpdate
Dim ForecastEntries(1)
Dim ForecastLayout0(6,4) '0=Day, 1=Temp, 2=Precip, 3=WeatherDescription, 4=WeatherCode
Dim ForecastLayout1(6,4)
Dim Maximum, Minimum
YahooURL = "http://xml.weather.yahoo.com/forecastrss"
ZipCode = "75022"
Units = "f"
'ZipCode = GetPropertyValue("CurrentWeather.CWZipCode")
'Units = GetPropertyValue("CurrentWeather.CWUnits")
YahooURL = YahooURL & "?p=" & ZipCode & "&u=" & Units
Main
Private Sub Main()
YahooXML = GetXMLData(YahooURL)
If YahooXML <> "" Then
ParseYahooXML
'SetHouseBotValues
End If
If Latitude <> "" And Longitude <> "" Then
NOAAURL = "http://forecast.weather.gov/MapClick.php?lat=" & Latitude & "&lon=" & Longitude & "&FcstType=dwml"
NOAAXML = GetXMLData(NOAAURL)
'Debug.Write NOAAXML
ParseNOAAXML
ProcessWeatherSummary
Debug.WriteLine "Layout"
Debug.WriteLine ForecastEntries(0)
Debug.WriteLine ForecastEntries(1)
For I = 0 To 6
Debug.WriteLine CStr(I)
Debug.WriteLine ForecastLayout0(I, 0) & ": " & ForecastLayout0(I, 1) & " " & ForecastLayout0(I, 2) & " " & ForecastLayout0(I, 3)
Debug.WriteLine ForecastLayout1(I, 0) & ": " & ForecastLayout1(I, 1) & " " & ForecastLayout1(I, 2) & " " & ForecastLayout1(I, 3)
Debug.WriteLine
Next
End If
End Sub
Private Function GetXMLData(ByVal URL)
Set XMLHTTP = CreateObject("microsoft.xmlhttp")
XMLHTTP.Open "GET", URL, True
XMLHTTP.send
I = 0
Do
WScript.Sleep(500)
If XMLHTTP.readyState = 4 Then
Exit Do
End If
If I = 8 Then
Exit Function
End If
I = I + 1
Loop
GetXMLData = XMLHTTP.responseText
Set XMLHTTP = Nothing
End Function
Private Sub ParseNOAAXML()
On Error Resume Next
Set xmlData = CreateObject("Microsoft.XMLDom")
xmlData.async = "false"
xmlData.loadXML(NOAAXML)
Dim Node
Dim ChildNode
For Each Node In xmlData.getElementsByTagName("data").item(0).childNodes
Select Case Node.nodeName
Case "location"
For Each ChildNode In Node.childNodes
Select Case ChildNode.nodeName
Case "location-key"
Case "description"
Case "point"
Case "city"
Case "height"
End Select
Next
Case "time-layout"
If Node.firstChild.nodeName = "layout-key" And InStr(Node.firstChild.text, "k-p24h") > 0 And InStr(Node.firstChild.text, "-1") > 0 Then
LayoutKey(0) = Node.firstChild.text
ForecastEntries(0) = CInt(Right(Left(LayoutKey(0), 9), 1)) - 1
I = 0
For Each ChildNode In Node.childNodes
Select Case ChildNode.nodeName
Case "start-valid-time"
ForecastLayout0(I, 0) = ChildNode.attributes.getNamedItem("period-name").text
I = I + 1
End Select
Next
End If
If Node.firstChild.nodeName = "layout-key" And InStr(Node.firstChild.text, "k-p24h") > 0 And InStr(Node.firstChild.text, "-2") > 0 Then
LayoutKey(1) = Node.firstChild.text
ForecastEntries(1) = CInt(Right(Left(LayoutKey(1), 9), 1)) - 1
I = 0
For Each ChildNode In Node.childNodes
Select Case ChildNode.nodeName
Case "start-valid-time"
ForecastLayout1(I, 0) = ChildNode.attributes.getNamedItem("period-name").text
I = I + 1
End Select
Next
End If
Case "parameters"
For Each ChildNode In Node.childNodes
Select Case ChildNode.nodeName
Case "temperature"
If ChildNode.attributes.getNamedItem("type").text = "maximum" Then
I = 0
For Each A In ChildNode.childNodes
If ChildNode.attributes.getNamedItem("time-layout").text = LayoutKey(0) Then
Maximum = 0
If A.nodeName = "value" Then
ForecastLayout0(I, 1) = A.text
If Units = "f" Then
ForecastLayout0(I, 1) = ForecastLayout0(I, 1) & Chr(176) & "F"
Else
ForecastLayout0(I, 1) = Left(CStr((CInt(ForecastLayout0(I, 1)) - 32)*5/9), InStr(CStr((CInt(ForecastLayout0(I, 1)) - 32)*5/9), ".") - 1) & Chr(176) & "C"
End If
I = I + 1
End If
End If
Next
I = 0
For Each A In ChildNode.childNodes
If ChildNode.attributes.getNamedItem("time-layout").text= LayoutKey(1) Then
Maximum = 1
If A.nodeName = "value" Then
ForecastLayout1(I, 1) = A.text
If Units = "f" Then
ForecastLayout1(I, 1) = ForecastLayout1(I, 1) & Chr(176) & "F"
Else
ForecastLayout1(I, 1) = Left(CStr((CInt(ForecastLayout1(I, 1)) - 32)*5/9), InStr(CStr((CInt(ForecastLayout1(I, 1)) - 32)*5/9), ".") - 1) & Chr(176) & "C"
End If
I = I + 1
End If
End If
Next
End If
If ChildNode.attributes.getNamedItem("type").text = "minimum" Then
I = 0
For Each A In ChildNode.childNodes
If ChildNode.attributes.getNamedItem("time-layout").text = LayoutKey(0) Then
Minimum = 0
If A.nodeName = "value" Then
ForecastLayout0(I, 1) = A.text
If Units = "f" Then
ForecastLayout0(I, 1) = ForecastLayout0(I, 1) & Chr(176) & "F"
Else
ForecastLayout0(I, 1) = Left(CStr((CInt(ForecastLayout0(I, 1)) - 32)*5/9), InStr(CStr((CInt(ForecastLayout0(I, 1)) - 32)*5/9), ".") - 1) & Chr(176) & "C"
End If
I = I + 1
End If
End If
Next
I = 0
For Each A In ChildNode.childNodes
If ChildNode.attributes.getNamedItem("time-layout").text = LayoutKey(1) Then
Minimum = 1
If A.nodeName = "value" Then
ForecastLayout1(I, 1) = A.text
If Units = "f" Then
ForecastLayout1(I, 1) = ForecastLayout1(I, 1) & Chr(176) & "F"
Else
ForecastLayout1(I, 1) = Left(CStr((CInt(ForecastLayout1(I, 1)) - 32)*5/9), InStr(CStr((CInt(ForecastLayout1(I, 1)) - 32)*5/9), ".") - 1) & Chr(176) & "C"
End If
I = I + 1
End If
End If
Next
End If
Case "probability-of-precipitation"
I = 0
P = 0
For Each A In ChildNode.childNodes
If Maximum = 0 Then
If A.nodeName = "value" Then
If I <= ForecastEntries(0) Then
If A.text <> "" Then
ForecastLayout0(I, 2) = A.text & "%"
Else
ForecastLayout0(I, 2) = "0%"
End If
Else
If A.text <> "" Then
ForecastLayout1(P, 2) = A.text & "%"
Else
ForecastLayout1(P, 2) = "0%"
End If
P = P + 1
End If
I = I + 1
End If
Else
If A.nodeName = "value" Then
If I <= ForecastEntries(1) Then
If A.text <> "" Then
ForecastLayout1(I, 2) = A.text & "%"
Else
ForecastLayout1(I, 2) = "0%"
End If
Else
If A.text <> "" Then
ForecastLayout0(P, 2) = A.text & "%"
Else
ForecastLayout0(P, 2) = "0%"
End If
P = P + 1
End If
I = I + 1
End If
End If
Next
Case "weather"
I = 0
P = 0
For Each A In ChildNode.childNodes
If Maximum = 0 Then
If A.nodeName = "weather-conditions" Then
If I <= ForecastEntries(0) Then
ForecastLayout0(I, 3) = A.attributes.getNamedItem("weather-summary").text
Else
ForecastLayout1(P, 3) = A.attributes.getNamedItem("weather-summary").text
P = P + 1
End If
I = I + 1
End If
Else
If A.nodeName = "value" Then
If I <= ForecastEntries(1) Then
ForecastLayout1(I, 3) = A.attributes.getNamedItem("weather-summary").text
Else
ForecastLayout0(P, 3) = A.attributes.getNamedItem("weather-summary").text
P = P + 1
End If
I = I + 1
End If
End If
Next
End Select
Next
End Select
Next
End Sub
Private Sub ProcessWeatherSummary()
For I = 0 To ForecastEntries(0)
ForecastLayout0(I, 3) = Replace(ForecastLayout0(I, 3), "Chc", "Chance")
ForecastLayout0(I, 3) = Replace(ForecastLayout0(I, 3), "Tstms", "T-storms")
Next
For I = 0 To ForecastEntries(0)
ForecastLayout1(I, 3) = Replace(ForecastLayout1(I, 3), "Chc", "Chance")
ForecastLayout1(I, 3) = Replace(ForecastLayout1(I, 3), "Tstms", "T-storms")
Next
End Sub
Private Sub ParseYahooXML()
On Error Resume Next
Set xmlData = CreateObject("Microsoft.XMLDom")
xmlData.async = "false"
xmlData.loadXML(YahooXML)
City = xmlData.getElementsByTagName("yweather:location").item(0).getAttribute("city")
State = xmlData.getElementsByTagName("yweather:location").item(0).getAttribute("region")
Country = xmlData.getElementsByTagName("yweather:location").item(0).getAttribute("country")
Units_Temp = xmlData.getElementsByTagName("yweather:units").item(0).getAttribute("temperature")
Units_Dist = xmlData.getElementsByTagName("yweather:units").item(0).getAttribute("distance")
Units_Pres = xmlData.getElementsByTagName("yweather:units").item(0).getAttribute("pressure")
Units_Spd = xmlData.getElementsByTagName("yweather:units").item(0).getAttribute("speed")
WindChill = xmlData.getElementsByTagName("yweather:wind").item(0).getAttribute("chill") & Chr(176) & Units_Temp
WindSpeed = xmlData.getElementsByTagName("yweather:wind").item(0).getAttribute("speed") & " " & Units_Spd
WindDirection = xmlData.getElementsByTagName("yweather:wind").item(0).getAttribute("direction")
Humidity = xmlData.getElementsByTagName("yweather:atmosphere").item(0).getAttribute("humidity") & " %"
Visibility = xmlData.getElementsByTagName("yweather:atmosphere").item(0).getAttribute("visibility")
Pressure = xmlData.getElementsByTagName("yweather:atmosphere").item(0).getAttribute("pressure") & " " & Units_Pres
Rising = xmlData.getElementsByTagName("yweather:atmosphere").item(0).getAttribute("rising")
If CInt(Rising) = 0 Then
Rising = "Steady"
ElseIf CInt(Rising) = 1 Then
Rising = "Rising"
ElseIf CInt(Rising) = 2 Then
Rising = "Falling"
End If
Sunrise = xmlData.getElementsByTagName("yweather:astronomy").item(0).getAttribute("sunrise")
Sunset = xmlData.getElementsByTagName("yweather:astronomy").item(0).getAttribute("sunset")
Latitude = xmlData.getElementsByTagName("geo:lat").item(0).text
Longitude = xmlData.getElementsByTagName("geo:long").item(0).text
Condition = xmlData.getElementsByTagName("yweather:condition").item(0).getAttribute("text")
Code = xmlData.getElementsByTagName("yweather:condition").item(0).getAttribute("code")
If Len(Code) <> 2 Then
Code = "0" & Code
End If
Temperature = xmlData.getElementsByTagName("yweather:condition").item(0).getAttribute("temp") & Chr(176) & Units_Temp
LastUpdate = xmlData.getElementsByTagName("yweather:condition").item(0).getAttribute("date")
For I = 0 To 1
Forecast(I, 0) = xmlData.getElementsByTagName("yweather:forecast").item(I).getAttribute("day")
Forecast(I, 1) = xmlData.getElementsByTagName("yweather:forecast").item(I).getAttribute("date")
Forecast(I, 2) = xmlData.getElementsByTagName("yweather:forecast").item(I).getAttribute("low")
Forecast(I, 3) = xmlData.getElementsByTagName("yweather:forecast").item(I).getAttribute("high")
Forecast(I, 4) = xmlData.getElementsByTagName("yweather:forecast").item(I).getAttribute("text")
Forecast(I, 5) = xmlData.getElementsByTagName("yweather:forecast").item(I).getAttribute("code")
If Len(Forecast(I,5)) <> 2 Then
Forecast(I,5) = "0" & Forcast(I,5)
End If
Next
Set xmlData = Nothing
End Sub
Private Sub SetHouseBotValues()
Call SetPropertyValue(".CWVisibility", Visibility)
Call SetPropertyValue(".CWWindChill", WindChill)
Call SetPropertyValue(".CWWindSpeed", WindSpeed)
Call SetPropertyValue(".CWWindDirection", WindDirection)
Call SetPropertyValue(".CWHumidity", Humidity)
Call SetPropertyValue(".CWBarometer", Pressure)
Call SetPropertyValue(".CWRising", Rising)
Call SetPropertyValue(".CWWeather", Condition)
Call SetPropertyValue(".CWTemperature", Temperature)
Call SetPropertyValue(".CWLocation", City & ", " & State & " (" & Country & ")")
Call SetPropertyValue(".CWTime", LastUpdate)
Call SetPropertyValue(".CWWeatherNumber", "C:\Program Files\HouseBot\Config\Themes\Weather Images\" & Code & ".png")
Call SetPropertyValue(".CWDay", Forecast(0,0))
Call SetPropertyValue(".CWDate", Forecast(0,1))
Call SetPropertyValue(".CWLow", Forecast(0,2) & Chr(176) & Units_Temp)
Call SetPropertyValue(".CWHigh", Forecast(0,3) & Chr(176) & Units_Temp)
Call SetPropertyValue(".CWForecastDay", Forecast(1,0))
Call SetPropertyValue(".CWForecastDate", Forecast(1,1))
Call SetPropertyValue(".CWForecastLow", Forecast(1,2) & Chr(176) & Units_Temp)
Call SetPropertyValue(".CWForecastHigh", Forecast(1,3) & Chr(176) & Units_Temp)
Call SetPropertyValue(".CWForecastWeather", Forecast(1,4))
Call SetPropertyValue(".CWForecastWeatherNumber", "C:\Program Files\HouseBot\Config\Themes\Weather Images\" & Forecast(1,5) & ".png")
End Sub