Add to Technorati Favorites
Welcome to ThePowerShellGuy.com Sign in | Join | Help

PowerShell V2 : Get-Weather function using a Web service

In PowerShell V2 using a Web service is very easy with the new Cmdlet New-WebServiceProxy,

As I will show in this post by creating a Small Get-Weather function.

 

On the site http://www.webservicex.com we can find a couple of Web services among them a Global Weather service that I will use in my PowerShell Get-Weather function.

If we choose Global Weather on the website above we find some links among them we find the WSDL Location URI

WSDL Location
http://www.webservicex.net/globalweather.asmx?wsdl

this will link to an XML page describing the services and that is all that we need to get started

first we create the webServiceProxy using the following command

$weather = New-WebServiceProxy -uri http://www.webservicex.com/globalweather.asmx?WSDL

and it might seem almost to simple but we are as good as done already, only one line to go ;-)

PS H:\> ([xml]$weather.GetWeather('Zurich-Kloten','Switzerland')).CurrentWeather

Location         : Zurich-Kloten, Switzerland (LSZH) 47-29N 008-32E 432M
Time             : May 15, 2009 - 06:20 AM EDT / 2009.05.15 1020 UTC
Wind             :  Variable at 3 MPH (3 KT):0
Visibility       :  greater than 7 mile(s):0
SkyConditions    :  mostly cloudy
Temperature      :  64 F (18 C)
DewPoint         :  53 F (12 C)
RelativeHumidity :  67%
Pressure         :  29.74 in. Hg (1007 hPa)
Status           : Success

And we are Ready !, I got the current Weather in my region from a Web service in PowerShell V2 with only 2 lines !!.

But as that second line might be a bit cryptic lets look how I came to that

Now we have the $Weather object lets look at it with the Get-Member Cmdlet :

$weather | get-member

We can find 2 methods in the output from Get-member that look interesting :

GetCitiesByCountry

GetWeather

Lets look at that first Method :

PS H:\> $weather.GetCitiesByCountry

MemberType          : Method
OverloadDefinitions : {string GetCitiesByCountry(string CountryName)}
TypeNameOfValue     : System.Management.Automation.PSMethod
Value               : string GetCitiesByCountry(string CountryName)
Name                : GetCitiesByCountry
IsInstance          : True

Using a Methodname without parentheses in PowerShell we get information about the Method, by looking at the overloads we can see that, as you might have expected it takes a Countryname as Parameter.

so lets try that for Switzerland where I live

PS H:\> $weather.GetCitiesByCountry('Switzerland')
<NewDataSet>
  <Table>
    <Country>Switzerland</Country>
    <City>Geneve-Cointrin</City>
  </Table>
  <Table>
    <Country>Switzerland</Country>
    <City>Lausanne</City>
  </Table>
  <Table>
    <Country>Switzerland</Country>
    <City>Neuchatel</City>
  </Table>
  <Table>
    <Country>Switzerland</Country>
    <City>Sion</City>
  </Table>
  <Table>
    <Country>Switzerland</Country>
    <City>Payerne</City>
  </Table>
  <Table>
    <Country>Switzerland</Country>
    <City>Lugano</City>
  </Table>
  <Table>
    <Country>Switzerland</Country>
    <City>Bern / Belp</City>
  </Table>
  <Table>
    <Country>Switzerland</Country>
    <City>Grenchen</City>
  </Table>
  <Table>
    <Country>Switzerland</Country>
    <City>Zurich-Kloten</City>
  </Table>
  <Table>
    <Country>Switzerland</Country>
    <City>Saint Gallen-Altenrhein</City>
  </Table>
</NewDataSet>

And you can see we get back some XML with all the City’s we can pick in Switzerland.

This gives us the information we need but not in a handy format, but no problem as PowerShell perfectly knows how to handle XML for us, we just need to cast it to an XML  object like this :

PS H:\> $xml = [xml]$weather.GetCitiesByCountry('Switzerland')
PS H:\> $xml

NewDataSet
----------
NewDataSet

PS H:\> $xml.NewDataSet

Table
-----
{Table, Table, Table, Table...}

PS H:\> $xml.NewDataSet.table

Country                                                     City
-------                                                     ----
Switzerland                                                 Geneve-Cointrin
Switzerland                                                 Lausanne
Switzerland                                                 Neuchatel
Switzerland                                                 Sion
Switzerland                                                 Payerne
Switzerland                                                 Lugano
Switzerland                                                 Bern / Belp
Switzerland                                                 Grenchen
Switzerland                                                 Zurich-Kloten
Switzerland                                                 Saint Gallen-Altenrhein

Much better not ?

now we can select the City we need lets look at the second method GetWeather

PS H:\> $weather.GetWeather

MemberType          : Method
OverloadDefinitions : {string GetWeather(string CityName, string CountryName)}
TypeNameOfValue     : System.Management.Automation.PSMethod
Value               : string GetWeather(string CityName, string CountryName)
Name                : GetWeather
IsInstance          : True

Again no surprises here I think it takes a City and a Country as Parameters.

As we found the city we where interested in lets try it

PS H:\> $weather.GetWeather('Zurich-Kloten','Switzerland')
<?xml version="1.0" encoding="utf-16"?>
<CurrentWeather>
  <Location>Zurich-Kloten, Switzerland (LSZH) 47-29N 008-32E 432M</Location>
  <Time>May 15, 2009 - 06:20 AM EDT / 2009.05.15 1020 UTC</Time>
  <Wind> Variable at 3 MPH (3 KT):0</Wind>
  <Visibility> greater than 7 mile(s):0</Visibility>
  <SkyConditions> mostly cloudy</SkyConditions>
  <Temperature> 64 F (18 C)</Temperature>
  <DewPoint> 53 F (12 C)</DewPoint>
  <RelativeHumidity> 67%</RelativeHumidity>
  <Pressure> 29.74 in. Hg (1007 hPa)</Pressure>
  <Status>Success</Status>
</CurrentWeather>

And we get back the Weather, again as XML but as we have seen above that is really no problem, we just cast it to [XML] again.

PS H:\> [xml]$weather.GetWeather('Zurich-Kloten','Switzerland')

xml                                                         CurrentWeather
---                                                         --------------
version="1.0" encoding="utf-16"                             CurrentWeather

PS H:\> ([xml]$weather.GetWeather('Zurich-Kloten','Switzerland')).CurrentWeather

Location         : Zurich-Kloten, Switzerland (LSZH) 47-29N 008-32E 432M
Time             : May 15, 2009 - 06:20 AM EDT / 2009.05.15 1020 UTC
Wind             :  Variable at 3 MPH (3 KT):0
Visibility       :  greater than 7 mile(s):0
SkyConditions    :  mostly cloudy
Temperature      :  64 F (18 C)
DewPoint         :  53 F (12 C)
RelativeHumidity :  67%
Pressure         :  29.74 in. Hg (1007 hPa)
Status           : Success

We can make a little helper function now to make it even simpler

Function Get-Weather ([switch]$list,$city = 'Zurich-Kloten',$country = 'Switzerland',$filter = '') {

  $weather = New-WebServiceProxy -uri http://www.webservicex.com/globalweather.asmx?WSDL

  if ($list) {
    ([xml]$weather.GetCitiesByCountry($filter)).NewDataSet.table
  } else {
    ([xml]$weather.GetWeather($City,$country)).CurrentWeather
  }
}

And now we can use it like this :

To find out what the weather in the Netherlands where I lived before I can simple use the following 2 commands to find the City and to get the Weather :

PS H:\> Get-Weather -list -filter netherlands

Country                                                     City
-------                                                     ----
Netherlands                                                 Amsterdam Airport Schiphol
Netherlands                                                 Maastricht Airport Zuid Limburg
Netherlands                                                 De Bilt
Netherlands                                                 Deelen
Netherlands                                                 Eindhoven
Netherlands                                                 Groningen Airport Eelde
Netherlands                                                 Gilze-Rijen
Netherlands                                                 De Kooy
Netherlands                                                 Leeuwarden
Netherlands                                                 Rotterdam Airport Zestienhoven
Netherlands                                                 Soesterberg
Netherlands                                                 Twenthe
Netherlands                                                 Valkenburg
Netherlands                                                 Volkel
Netherlands                                                 Vlieland
Netherlands                                                 Woensdrecht
Netherlands Antilles                                        Flamingo Airport, Bonaire
Netherlands Antilles                                        Hato Airport, Curacao
Netherlands Antilles                                        Roosevelt Airport Saint Eustatius
Netherlands Antilles                                        Juliana Airport, Saint Maarten

PS H:\> Get-Weather -country Netherlands -city Eindhoven

Location         : Eindhoven, Netherlands (EHEH) 51-27N 005-25E 28M
Time             : May 15, 2009 - 06:25 AM EDT / 2009.05.15 1025 UTC
Wind             :  from the WSW (240 degrees) at 10 MPH (9 KT):0
SkyConditions    :  overcast
Temperature      :  60 F (16 C)
DewPoint         :  55 F (13 C)
RelativeHumidity :  82%
Pressure         :  29.68 in. Hg (1005 hPa)
Status           : Success

Yihaa, it is 2 degrees warmer here ;-)

Enjoy,

Greetings /\/\o\/\/

Published Friday, May 15, 2009 6:39 AM by MoW

Comments

# re: PowerShell V2 : Get-Weather function using a Web service

Thanks for the post on weather access. I'd thought about doing this myself, linking my ham radio hobby. Why should I ever look outside when I can tell people the weather automatically. :-)

Tuesday, June 02, 2009 10:47 AM by cebess

# re: PowerShell V2 : Get-Weather function using a Web service

Thanks for the post on weather access. I'd thought about doing this myself, linking my ham radio hobby. Why should I ever look outside when I can tell people the weather automatically. :-)

Tuesday, June 02, 2009 10:47 AM by cebess

# Johan Andersson (johanandersson) 's status on Thursday, 20-Aug-09 20:16:45 UTC - Identi.ca

# Twitter Trackbacks for The PowerShell Guy : PowerShell V2 : Get-Weather function using a Web service [thepowershellguy.com] on Topsy.com

# What about proxies?

@MoW: Nice code snippet! Unfortunately, it doesn't work if your Internet connection requires a proxy (I receive a "New-WebServiceProxy : Fehler bei der Anforderung mit HTTP-Status 407: Proxy Authentication Required"). I'd just like to use the default credentials (=w/o prompting the user), but couldn't find a working solution that far?

Monday, April 12, 2010 7:02 AM by kairo

# re: What about proxies

Oh, I should have added: Of course, I get it to run when I use the old-style WebClient version:

$Url = "http://www.webservicex.net/WeatherForecast.asmx"

$webclient = new-object System.Net.WebClient

$saopMessage = @"

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">

 <soap:Body>

   <GetWeatherByPlaceName xmlns="http://www.webservicex.net">

     <PlaceName>New York</PlaceName>

   </GetWeatherByPlaceName>

 </soap:Body>

</soap:Envelope>

"@

$webclient.headers.Add("SOAPAction","http://www.webservicex.net/GetWeatherByPlaceName")

$webclient.headers.Add("Content-Type", "text/xml; charset=utf-8")

$WebClient.Proxy = [System.Net.WebRequest]::DefaultWebProxy;

$WebClient.Proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials;

$result = ([XML]$webclient.UploadString($Url,

$saopMessage)).envelope.body.GetWeatherByPlaceNameResponse.GetWeatherByPlaceNameResult

$result

$result.details.WeatherData

But I'd prefer a cool single-liner solution... :-))

Monday, April 12, 2010 7:27 AM by kairo

# Credential caching differs between WebServiceProxy and WebClient

Bummer; the more I delve in, the more confused I get.. :-)

I noticed that if I *force* the user re-entering his credentials, then it also works in a proxied/firewalled situation:

$c = get-credential

$weather = New-WebServiceProxy -uri "http://www.webservicex.com/globalweather.asmx?WSDL" -Credential $c

([xml]$weather.GetWeather('Zurich-Kloten','Switzerland')).CurrentWeather

However, as the V1 code with the WebClient object and the manual SOAP-msg before showed, this is unnecessary there, it suffices to provide the "DefaultCredential".

However, trying the obvious...

$c = [System.Net.CredentialCache]::DefaultCredentials

...and then proceed as before will fail again. -So obviously, the two objects treat the system credentials differently. It is as if the WebClient object has some way to trick CachedCredentials out of the IE object somehow, but the WebServiceProxy object doesn't???

-Hints welcome, as I don't force people to enter credentials over and over again...

Tuesday, April 13, 2010 8:13 AM by kairo
Anonymous comments are disabled