Christopher Blunck
blunck@gst.com
Release 0.2.1
March 27, 2003
WxNet is a network of meteorologists, publishing and consuming data according to a a well defined interface described in WSDL The Web Services Description Language 1.1. WeatherNet allows any weather observer to share and gather information over a commonly understood network using industry standard protocols. It also provides a mechanism by which an observer can register with the network and search the network for other observers based upon their geographic location.
WxNet is platform independant, but the reference implementations require Python 2.0 or later and ZSI obtained from CVS.
The WxNet homepage is at http://meta-tools.sf.net/.
This work is published under the GNU General Public License.
All Rights Reserved.
I am extremely grateful to Rich Salz of the ZSI project http://pywebsvcs.sf.net/ for his enourmous contribution to the Python for Web Services community. Without his code, WeatherNet would not be possible. Thanks, Rich.
I am also grateful to Neal Norwitz and Eric Newton of http://www.metaslash.com/ for introducing me to Python and for answering my barrage of annoying questions. Thanks guys.
WxNet, WeatherNet, is a network of weather observers who share and discover meteorological data using well defined APIs over a standard network interface. When connected to the network, any WeatherNet-aware client can connect and receive meteorological data from any station on the network. This data could be used for graphical display, forecasting, or any other general purpose. Similarly, weather providers are able to connect to the network and share data with anyone they like.
WxNet is platform independant, but the reference implementation requires Python 2.0 or later as well as ZSI available from :pserver:anonymous@cvs.sourceforge.net/cvsroot/pywebsvcs.
The WxNet homepage is at http://meta-tools.sf.net/.
This project centers around Web Services. The purpose of web services is to provide a standard format for defining publicly accessible operations implemented on a remote computer. Using web services, a service provider can define operations they have implemented as well as the data structures passed and returned from said operations. Although it is not required, most web services are accessed via The SOAP 1.1 Specification, which allows for transport independance. This means that a client can interact with a SOAP server via http, smtp, ftp, or any other protocol so long as it is explicitly stated in the definition of the interface. As a best practice, most people use http as a transport protocol for SOAP.
A benefit of using WSDL is the decomposition that occurs when analysing a weather network service oriented architecture. In order to participate on the WeatherNet, an observer need only conform to the interface defined by this project. How you implement that interface is completely up to you: you could report meterological data in real time, or you could pull said data from a database. It simply doesn't matter, so long as you implement the published interface.
Using the WeatherNet architecture, a variety of clients can be written. A reference implementation exists that connects to an observer on the WeatherNet and displays the current weather information. In the future, more complex clients could be written to make use of a single capability: collection of data from different geographic locations. The harvesting capability WeatherNet provides supports a variety of use cases, the most significant of which is more data to provide to forecasting models.
The heart of the WeatherNet project is the published WeatherNet interface, which all data providers participating on the network must implement. The definition of the interface is via the Web Services Description Language, providing a high level of interoperability between servers and clients.
WeatherNet defines three complex data types: RainSummary, WindSummary, and Summary, each of which corresponds to a python class. Summary is an aggregation of RainSummary and WindSummary as well as some additional fields that summarize the current state of a weather station. These includes vital information such as temperature, barometric pressure, dew point, sunrise (and sunset), as well as local station time.
The class definition for a RainSummary follows:
class RainSummary: def __init__(self, rate=0.0, storm=0.0, day=0.0, month=0.0, year=0.0, stormStartDate=None): self.rate = rate self.stormTotal = storm self.dayTotal = day self.monthTotal = month self.yearTotal = year self.stormStartDate = stormStartDate
The fields contained within a RainSummary represent rain totals over various time periods. The dayTotal, monthTotal, and yearTotal fields represent the total rain accumulation (in inches) over the previous day, month, and year respectively. The values are not relative, meaning if it is February 15, the value in the monthTotal represents the total rain accumulation between February 1 and February 15, inclusive. Likewise, the day total is since midnight of the current day, as opposed to the total over the past 24 hours.
The class definition for a WindSummary follows:
class WindSummary: def __init__(self, speed=0, dir=0, speed10min=0): self.speed = speed self.direction = dir self.speed10min = speed10min
The fields contained within a WindSummary represent the current wind status, including the 10 minute historical average for the wind speed. The 10 minute historical wind speed average may or may not be of professional signifigance, but has been included because my person weather station reports it and I thought it best to share it just in case. The speed is an integer and is in mph, and the direction is also an integer representing the direction the wind is currently blowing from ([0 - 360)).
The class information for a Summary follows:
class Summary: def __init__(self, datestamp=None, pressure=0.0, temperature=0.0, windsummary=None, rainsummary=None, sunrise=None, sunset=None, dewpoint=0.0, humidity=0.0): self.datestamp = datestamp self.pressure = pressure self.temperature = temperature self.windsummary = windsummary self.rainsummary = rainsummary self.sunrise = sunrise self.sunset = sunset self.dewpoint = dewpoint self.humidity = humidity
A Summary represents a snapshot of the current meteorological data from an observer. Contained within are the complex types of WindSummary and RainSummary, both of which are described above. Additionally, a Summary defines important primitives like the current temperature (in Fahrenheit), barometric pressure (in inches of mercury), sunrise and sunset (standard python time tuples), dewpoint (in Fahrenheight), and the relative humidity. The datestamp field represents the local time of the station in Python time tuple format. A Summary is an good complex type to use as a client because it contains all information a provider on the WeatherNet can supply, and is easily transported.
The list of operations follows:
# wind sensors def getWindSpeed() def getWindDir() def getWindSummary() # rain sensors def isCurrentlyRaining() def getRainRate() def getRainDay() def getRainMonth() def getRainYear() def getStormStartDate() # core sensors def getTemperature() def getPressure() def getRelativeHumidity() def getSunrise() def getSunset() def getDewPoint() def getLocalTime() # summary information def getSummary()
The getLocalTime() operation must be implemented.
Servers are producers of meteorological observerations distributed via the WeatherNet network. The implementation details of a WeatherNet server are insignificant as long as the published interface is supported.
Additionally, a server programmer may choose to implement a superset or subset of the operations defined in WeatherNet to return actual data, but is not required to do so. In the situation where a server cannot (or does not wish to) provide complete coverage of the WeatherNet interface, unsupported operations should be stubbed in order to insure compliance with the standard. Thus, if a participant wishes to be a provider, but does not have an anemometer, they can simply return a WindSummary with speed, direction, and 10 minute average as 0, 0, and 0.
There is no support available (yet) for publishing of supersets of operations that WeatherNet does not provide. I have considered this, and believe that it will be an important problem to solve. But given the current lack of a community, I decided not to implement that functionality until requested.
Python was chosen as the language used for the reference implementation because the loosely typed nature of the language lends itself nicely to web services development. The libraries in Python (ZSI in particular) are extremely easy to use, and do not require the use of external tools (WSDL -> Stub generators), making prototyping and development extremely painless and simple. This is a credit to both the language and the ZSI project for providing such an intuitive interface.
The server side reference implementation retrieves data from a database. This could easily be adapted to read data in realtime from a weather station, but given the native hardware issues involved (and the lack of support from our weather hardware supplier), this was both impractical and difficult. A database seemed to be a fairly platform independant location with an easy to understand interface, and thus it was selected as the platform for our reference implementation.
The code for the server side reference implementation is stored in the server module in server/python directory. As such we will not include the entire source code in this document. Full examination of the reference implementation is recommended, and this document is really intended to whet your apetite for a feature-rich example (the reference implementation contained with the WeatherNet distribution).
Contained below is a snippit of our server side implementation:
#! /usr/bin/env python import sys, MySQLdb, time from ZSI import * from ComplexTypes import * DB_HOST=''localhost'' DB_USER=''Home_Weather'' DB_PASSWD=''Home_Weather'' DB=''Home_Weather'' def getPressure(): cursor.execute('select bar from Current') return cursor.fetchone()[0] def getWindSummary(): cursor.execute('select windspeed, winddir, windspeed10min from Current') speed, dir, speed10min = cursor.fetchone() return WindSummary(speed, dir, speed10min) # bind to the database, and obtain a cursor db = MySQLdb.connect(host=DB_HOST, user=DB_USER, passwd=DB_PASSWD, db=DB) cursor = db.cursor() # launch the service as a CGI, using wxnet as a namespace for complex types if __name__ == '__main__': nsdict = { 'wxnet' : 'http://wxnet.dnsalias.com/WxNet' } dispatch.AsCGI(nsdict=nsdict)
This server side implementation demonstrates two functionalities: getPressure and getWindSummary. The getPressure function returns a primitive, and the getWindSummary function returns a complex type. As a provider, you may choose to report data in realtime, or you can (as we did) report data stored in a database. This is the benefit of coding to an interface - you have the ability to implement according to your own requirements, desires, capabilities, or restrictions.
Thankfully, ZSI supports complex structures. This allows you as a WeatherNet provider to return complex data structures (like WindSummary). For more information on the deatils of serialization and deserialization of complex structures in ZSI, see http://pywebsvcs.sf.net/.
Clients are consumers of meterological observations published via the WeatherNet network. Similar to a server, what a client chooses to do with the information is beyond the scope of the WeatherNet project. Because the WeatherNet interface is published (and thus adhered to by all server particpants), a client has the ability to ``roam'' on the WeatherNet network, connecting to any server and displaying data in realtime (as long as the server provides data in realtime).
In the future, clients will be able to query a central node (the WeatherNet controller) to ask for a list of connected servers in the network. This list will most likely include the geographic location of each server, giving the client maximum flexibility in defining which server should be used.
The client side reference implementation uses Python for many of the same reasons that the server side reference implementation uses Pyhon. Loosely typed classes work very well with web services, making it very easy to develop a web service proxy.
The goal of the client side interface is to connect to a server and ask for the current weather conditions. ZSI was used on the client side to provide connectivity (primarily because it supports both WSDL parsing and SOAP binding), but any language and any project (or COTS software) could be used in replacement of ZSI because WeatherNet operates at the WSDL level, and thus is a highly interoperable network.
Below is code that connects to a WeatherNet server, and requests some weather information:
#! /usr/bin/env python from ZSI.wsdl import ServiceProxy from ZSI import * from ZSI.client import * def main(): wxnet = ServiceProxy(``http://wxnet.dnsalias.com/Weather/WxNet.wsdl'') pressure = wxnet.getPressure() print 'The current weather conditions are as follows:' print 'Pressure: %.4f' % summary.pressure (speed, dir, speed10min) = wxnet.getWindSummary() print 'Wind: %d at %d mph' % (speed, dir) if __name__ == '__main__': sys.path.append('../../common/python') main()
from ZSI import TC class WindSummary: def __init__(self, speed=0, dir=0, speed10min=0): self.speed = speed self.direction = dir self.speed10min = speed10min WindSummary.typecode = TC.Struct(WindSummary, [TC.Ilong('speed'), TC.Ilong('direction'), TC.Ilong('speed10min')], 'wxnet:WindSummary')
If you do not store the definition for WindSummary in ComplexTypes and append it to sys.path prior to invoking your webservice, you will need to call wxnet.ReceiveRaw(WindSummary) after invoking the remote operations. As a best practice, WeatherNet plans to define a set of common libraries for various languages to facilitate information passing between client and server. Python is currently the only support language of such middleware classes.
A client is free to use the WeatherNet information in any way, shape, or form. It can be returned to the end user in graphical format, forwarded to another weather network or organization, or even fed as input into forecasting models for the National Weather Service.
WeatherNet is simply an interface that describes operations common to most weather observing stations. Because it is an interface definition, it allows for numerous client and server side applications, that can ultimately support a wide variety of business needs. WeatherNet uses industry standards such as WSDL and SOAP to facilitate interoperability, and aims to be as unobtrusive as possible.
It is hoped that the WeatherNet project will be used as a starting point for more complex meterological network used by hundreds of amateur and profession meterologists to publish and share data.
This document was generated using the LaTeX2HTML translator.
LaTeX2HTML is Copyright © 1993, 1994, 1995, 1996, 1997, Nikos Drakos, Computer Based Learning Unit, University of Leeds, and Copyright © 1997, 1998, Ross Moore, Mathematics Department, Macquarie University, Sydney.
The application of LaTeX2HTML to the Python documentation has been heavily tailored by Fred L. Drake, Jr. Original navigation icons were contributed by Christopher Petrilli.