Fieldcimate
Developing Your Own
Applications
PIKernel Data
Interface makes it easy to develop
·
Customized Back-End applications
·
Disease and Forecast Modules
·
Data Conversion Modules
·
Database Replication Modules
· Interfaces to 3rd
party software
Get instant access
to your iMetos weather data programmatically
·
From any device connected to internet
·
Without database
·
Without web hosting
·
Using any development tool
Table of Content
Foreword For Windows Developers
General Description of Data Structures
Getting Configuration of Station
Diesease Models and Weather Forecast
PIKernel Data Interface is a SOAP based interface
to access the climate data of the weather stations. Developers can access it
directly through WSDL (see SOAP description). This assumes some familiarity
with SOAP Protocol. The interface covers all aspects of iMetos data. It
includes list of stations, its parameters and, of course, weather data. Weather
data can be read in any portion in different format from any date. It can be
grouped by hour, day or month. Page-like navigation is very easy as interface
provides possibility to read previous and next block relatively to the last
block read.
As of March 2007 the data interface is
read-only. It is not possible to set parameters of the weather station or store
any data.
For PHP developers, Pessl Instruments offers a
library of classes that greatly simplifies the development process. Using this
library you don't need to learn anything about underlying protocols and can
access fieldclimate data as if it were located on the same computer with your
application. All calls are internally translated to SOAP and dispatched to the
fieldclimate web site. The classes are arranged in a very convenient way and
PHP developers will feel comfortable working with them. Those, who are eager to
start digging the source code, please refer to a sample application at index.php
Pessl Instruments is planning to develop
similar libraries for VB, Delphi and Java
developers. If you want to participate in this work, you are very welcome. We
will be happy to receive your proposals at software@metos.at
. Specially, we need Java specialists with SOAP experience.
If you never heard of SOAP here are some
highlights
SOAP
·
Is
a [simple?] XML-based protocol to let applications exchange information
· Is a web consortium standard
·
Supported
by many popular development tools like Delphi, Visual Basic, PHP, .NET, Java
etc.
·
Used
by many industrial web services and well understood by web development
community
·
Microsoft
.NET framework mainly relies on SOAP for remote procedure calls and natively
supports it
For more
information you can have a look at
http://en.wikipedia.org/wiki/SOAP
- Short description of SOAP features
http://www.w3.org/TR/soap12-part0/
- SOAP specification from WWW consortium
The WSDL file is located at http://metos.at/cidiwsdl.php
It is implemented with the freeware PHP library
NUSOAP. If you open this URL in your browser you will see something like this
This is the list of functions exposed by
iMetosSOAP interface. If you click on any function, the list of parameters will
be shown at the right side. Clicking on the WSDL link will open WSDL file. Detailed
description of WSDL of PIKernel data interface is out of scope of this
document. For more information read the comments in the WSDL.
What is bad with simple XML format? It looks
very easy to make an XML interface, put all data of the station in one document
and let other application access it. There are plenty of XML tools available
for every platform and OS.
The problem is that parsing of XML document is
relatively complex. It is difficult to divide the interface into different functions.
For example, if we need to implement a function that delivers the list of
stations and another function that delivers data for a particular station we
have to define two different xml formats. Furthermore we need to parameterise
the data request to define the date and amount of weather data.
Parameterisation can be done by sending an xml file to the server. This would
be one more xml format. With complex interface and many different data
structures we would end up with tens of different xml specifications that are
not possible to manage.
SOAP solves all of those problems by defining
the rules to implement remote procedure calls. At the very high level it looks
like normal functions with parameters.
For those who still want to user a pure XML, we
support XML data interface. For details refer to http://fieldclimate.com/pikernel/download/imetos.zip
Foreword For Windows
Developers
If you are going to develop a windows
application using Fieldcliamte weather data you can consider one more, probably
easier way to get to the data - Synchronization Module. Synchronization module
is a small application that synchronizes Fieldcliamte data with a local
MSACCESS database on customers PC. It is available as a windows executable or
ActiveX module. This can give you some advantages against using the data
interface directly. The most notable is that internet traffic is considerably
reduced because the data is replicated only once. Another advantage is that
many development tools offer easy ways to work with the database. If you prefer
to work with MSACCESS database refer to
http://www.metos.at/pikernel/download/windows_sync/index.htm
Basically, there are tree main data structures
- list of stations, list of sensors of a station and data of a station.
List of stations returns all stations to which
the user has access. It includes name, serial number and some other parameters.
Having received this list one can query weather
data of a particular station. Weather data is transferred in small portions,
normally up to 1000 records, in order not to overload the server and
communication channel.
Depending on programming language, data can be
represented as a 2-dimensional array where every row is an associative array
(PHP) or as a recordset object (VB, Delphi, Java ).
If you work with PHP you can use the class
library provided by Pessl Instruments. It wrappers all SOAP calls in a nice
classes so that you don't need to deal with SOAP at all.
You start from reading out the list of
available station. First create a new instance of the class
PesslSOAPStationList
$soap_stations = & new
PesslSOAPStationList();
Then you need to provide the user name and
password
$soap_stations ->username = 'soap';
$soap_stations ->password = 'test';
That's all. Now we can read a list of stations
from fieldclimate
$stations = &
$soap_stations->PesslSOAPStationListAll() or die($soap_stations->error);
The function PesslSOAPStationListAll returns a
list of stations or false in case of error. Error message is saved in the error
variable
If stations have been read successfully
variable $stations is a 2-dimensional array representing a table with rows.
Every row is an associative array. The rows are very similar to those which are
returned by the mysql_fetch_array() functions where keys are the names of
fields.
Try to execute this script. Live demo is
available here station_list.php
<?php
require_once('class.pessl_soap.php');
$soap_stations =
& new PesslSOAPStationList();
$soap_stations
->username = 'soap';
$soap_stations
->password = 'test';
$stations = &
$soap_stations->PesslSOAPStationListAll() or
die("error reading station list: ".$soap_stations->error);
if(!count($stations)){
die("there are no stations available");
}
$fields=array_keys($stations[0]);
echo
"<table border=\"1\">";
echo
"<tr>";
foreach($fields as $f){
echo "<th> $f <th/>";
}
echo
"<tr/>";
foreach($stations as $row){
echo "<tr>";
foreach($row as $value){
echo "<td> $value <td/>";
}
echo "<tr>";
}
echo
"<table/>";
?>
Now we need to learn more about the stations.
To request data of a particular station, instantiate class PesslSOAPStation
$soap_station = & New PesslSOAPStation();
$soap_station->station_name =
$stations[0]['f_name'];
By assigning variable station_name we identify
the station we are interested in.
Again, we need the user name and password to
access data
$soap_station->username =
'soap';
$soap_station->password =
'test';
Now we can read out configuration of the
station using function PesslSOAPStation::PesslSOAPStationConfig()
$station_config = &
$soap_station->PesslSOAPStationConfig() or die($soap_station->error);
It returns 2-dimensional array. This array
contains only 1 row that is an associative array with the following fields
f_station_code
|
Ignore |
f_date
|
Date of
registration in database |
f_dev_id
|
Code of
device |
f_name
|
Name of
station |
f_descr
|
Textual
description of station |
f_info
|
Extended
textual description of the station |
f_uid |
Ignore |
F_create_time
|
Ignore |
F_measure_int
|
Measure
interval (0 - default) |
f_data_int
|
Logging
interval (0 - default) |
F_webserv_dom
|
Ignore |
F_webserv_url
|
Ignore |
F_webserv_port
|
Ignore |
f_emergency_sms
|
Ignore |
f_timezone
|
Time zone
in minutes (60=+1H -60 = -1H) |
f_latitude
|
Latitude |
f_longitude
|
Longitude |
F_hw_ver_major
|
Major
number of hardware version |
F_hw_ver_minor
|
Minor
number of hardware version |
F_sw_ver_major
|
Major number
of software version |
F_sw_ver_minor
|
Minor
number of software version |
f_sms_warn_numbers
|
Maximum
number of telephone numbers for SMS warnings |
f_sms_warn_values
|
Maximum
number of conditions for SMS warnings |
f_gsm_mcc
|
MCC code of
GSM operator |
f_gsm_mnc
|
MNC code
of GSM operator |
f_gprs_apn
|
APN of
GRPS connection |
f_gprs_user_id
|
User name
of GPRS connection |
F_gprs_passw
|
Password
for GPRS connection |
The following code is an example of reading station
configuration
It is also available here
<?php
require_once('class.pessl_soap.php');
$soap_stations = & new PesslSOAPStationList();
$soap_stations ->username = 'soap';
$soap_stations ->password = 'test';
$stations
= & $soap_stations->PesslSOAPStationListAll() or
die("error reading station list: ".$soap_stations->error);
if(!count($stations)){
die("there are no stations available");
}
$soap_station = & New PesslSOAPStation();
$soap_station->station_name = $stations[0]['f_name'];
$soap_station->username = 'soap';
$soap_station->password = 'test';
$station_config
= & $soap_station->PesslSOAPStationConfig() or
die($soap_station->error);
echo
"<h1> Configuration of station
".$soap_station->station_name."</h1>";
echo
"<table border=\"1\">";
$fields=array_keys($stations[0]);
$station_config=$station_config[0];
foreach($station_config as $k=>$v){
echo "<tr>";
echo "<th> $k </th>";
echo "<td> $v </td>";
echo "</tr>";
}
echo
"</table>";
?>
Next step is to read the list of sensors
connected to this station
$sensors = &
$soap_station->PesslSOAPStationSensors() or die($soap_station->error);
Again, the returned value is a 2-dimensional
array
Each row has the following fields
Field |
Meaning |
f_station_code |
Ignore |
f_sensor_ch |
Channel of the sensor. Every
sensor connected to the station has a unique channel number |
f_sensor_code |
Global code of the sensor. Every
model of sensor has its own code. Don't confuse with the channel. More then
one sensors with the same code can be connected to the same station, but
their channels will be different. For example, two air temperature sensors
with code 0 connected to the same station may have channels 0 and 1
respectively |
f_chain_code |
Code of chain is sensors are
chained. Some of sensors may be chained through a special cable. One chain may
have tens of different sensors. Through channel code one may group sensors by
chain to display or do some specific calculations |
f_group_code |
Code of group to which the sensor
belongs. Every model of sensor belongs to a globally defined group. For
example, all different air temperature sensors belong to one group, wind
speed sensors belong to another group, etc. Group allows recognising of
different sensors and unifying their parameters. |
f_unit_code |
Ignore |
f_name |
Original name of the sensor. Human
readable name of the sensor, assigned by Pessl Instruments |
f_unit f_div |
Ignore |
f_mul |
Ingnore |
f_val_neg |
Sensor may have negative values |
f_val_log |
Ignore |
f_val_last |
Last measured value is available |
f_val_sum |
Sum is available |
f_val_aver |
Average is available |
f_val_min |
Minimum value is available |
f_val_max |
Maximum value is available |
f_val_time |
Value is time interval |
f_val_user |
Ignore |
f_create_time |
Ignore |
f_group_name |
Name of group to which this sensor
belongs |
f_color |
HTML colour assigned to this
sensor in fieldclimate web site |
f_sensor_user_name |
User defined name for this sensor |
f_user_unit_code |
Ignore |
This script will show the list of sensors of
the first station from the station list.
Live demo is available here
<?php
require_once('class.pessl_soap.php');
$soap_stations = & new PesslSOAPStationList();
$soap_stations ->username = 'soap';
$soap_stations ->password = 'test';
$stations
= & $soap_stations->PesslSOAPStationListAll() or
die("error reading station list: ".$soap_stations->error);
if(!count($stations)){
die("there are no stations available");
}
$fields=array_keys($stations[0]);
echo
"<h1> List of stations </h1>";
echo
"<table border=\"1\">";
echo
"<tr>";
foreach($fields as $f){
echo "<th> $f </th>";
}
echo
"</tr>";
foreach($stations as $row){
echo "<tr>";
foreach($row as $value){
echo "<td> $value </td>";
}
echo "</tr>";
}
echo
"</table>";
$soap_station = & New PesslSOAPStation();
$soap_station->station_name = $stations[0]['f_name'];
$soap_station->username = 'soap';
$soap_station->password = 'test';
$sensors =
& $soap_station->PesslSOAPStationSensors() or
die("error reading sensors: ".$soap_station->error);
if(!count($sensors)){
die("there are no sensors available");
}
$fields=array_keys($sensors[0]);
echo
"<h1> Sensors of station
".$stations[0]['f_name']."</h1>";
echo
"<table border=\"1\">";
echo
"<tr>";
foreach($fields as $f){
echo "<th> $f </th>";
}
echo
"</tr>";
foreach($sensors as $row){
echo "<tr>";
foreach($row as $value){
echo "<td> $value </td>";
}
echo "</tr>";
}
echo
"</table>";
?>
Finally, as a reward for all our efforts and
patience we read the main value of the weather station - weather data. Class
PesslSOAPStation has the following functions to randomly access weather data
Function |
Description |
PesslSOAPStationDataGetFirst |
Reads first block of data |
PesslSOAPStationDataGetNext |
Reads next block of data |
PesslSOAPStationDataGetPrev |
Reads previous block of data |
PesslSOAPStationDataGetLast |
Reads last block of data |
PesslSOAPStationDataGetFromDate |
Reads block of data starting from
a specified date |
Variable row_count defines how many data records
one block should contain
Next and previous blocks are always calculated
relatively to the previous call using variable dt_from. This variable also
serves as a status of the object. To keep track between different http sessions
it is enough to recreate the PesslSOAPStation object and set dt_from.
Before calling PesslSOAPStationDataGetFromDate
dt_from should be implicitly set.
Like all previously mentioned interfaces,
weather data functions return a 2-dimensional array.
The number of columns and their names depend on
what sensors are connected to the station in question.
It is possible to read data grouped by hour,
day, and month or not grouped. To define the group function assign
PesslSOAPStation::group_code to
0 |
no group (default) |
1 |
hour |
2 |
day |
3 |
month |
First column always contains the date of the
measurement and is called f_date
Other column names are built according to the
scheme explained below
sens_aggr_ch_code
where aggr can be
aver |
Average value |
min |
Minimum value |
max |
Maximum value |
last |
Last value |
time |
Time |
ch channel of the sensor
Code code of the sensor
Example of data array
f_date |
sens_aver_0_16 |
sens_min_0_16 |
sens_max_0_16 |
sens_aver_3_1 |
sens_aver_4_0 |
sens_min_4_0 |
sens_max_4_0 |
sens_sum_5_6 |
sens_last_7_7 |
sens_time_8_4 |
sens_aver_20_21 |
sens_min_20_21 |
2006-04-07
15:00:00 |
26 |
26 |
26 |
28 |
27.4 |
27.4 |
27.4 |
|
6328 |
|
7.3 |
7.3 |
2006-04-07
16:00:00 |
26.2 |
25.4 |
27.2 |
21 |
25.1 |
19.4 |
27.1 |
|
6386 |
|
1.5 |
-5.4 |
sens_aver_0_16 means average value of sensor
with code 16 (soil temperature) connected to channel 0. This sensor also has
minimum and maximum values - sens_min_0_16 and sens_max_0_16. Next is sensor
with code 1 (Relative humidity) on channel 3. This sensor has only average
value.
To see the real weather data of a demo station,
execute this script.
It is also available here
<?php
require_once('class.pessl_soap.php');
$soap_stations = & new PesslSOAPStationList();
$soap_stations ->username = 'soap';
$soap_stations ->password = 'test';
$stations
= & $soap_stations->PesslSOAPStationListAll() or
die("error reading station list: ".$soap_stations->error);
if(!count($stations)){
die("there are no stations available");
}
$fields=array_keys($stations[0]);
echo
"<h1> List of stations </h1>";
echo
"<table border=\"1\">";
echo
"<tr>";
foreach($fields as $f){
echo "<th> $f </th>";
}
echo
"</tr>";
foreach($stations as $row){
echo "<tr>";
foreach($row as $value){
echo "<td> $value </td>";
}
echo "</tr>";
}
echo
"</table>";
$soap_station = & New PesslSOAPStation();
$soap_station->station_name = $stations[0]['f_name'];
$soap_station->username = 'soap';
$soap_station->password = 'test';
$station_data = & $soap_station->PesslSOAPStationDataGetFirst() or
die("error reading weather data: ".$soap_station->error);
if(!count($station_data)){
die("there is no data available");
}
$fields=array_keys($station_data[0]);
echo
"<h1> First block of weather data of station
".$stations[0]['f_name']."</h1>";
echo
"<table border=\"1\">";
echo
"<tr>";
foreach($fields as $f){
echo "<th> $f </th>";
}
echo
"</tr>";
foreach($station_data as $row){
echo "<tr>";
foreach($row as $value){
echo "<td>";
if($value){
echo $value;
}else{
echo " ";
}
echo "</td>";
}
echo "</tr>";
}
echo
"</table>";
?>
The names of columns are not very descriptive
in this example. To relate the columns to sensor information function
PesslSOAPStation::PesslSOAPGetInfoSensors has been designed.
This function accepts a name of column of
weather data and returns an array with information about the sensor related to
this column. The structure is same as in sensor array returned by
PesslSOAPStationSensors with one additional element with name f_aggr. This
element contains the name of aggregate function. It can be aver, max, min, last
or time depending on values of the sensor. Below is an example of using this
function to display the name of sensor and measurement unit in the header of
weather data table.
<?php
require_once('class.pessl_soap.php');
$soap_stations = & new PesslSOAPStationList();
$soap_stations ->username = 'soap';
$soap_stations ->password = 'test';
$stations
= & $soap_stations->PesslSOAPStationListAll() or
die("error reading station list: ".$soap_stations->error);
if(!count($stations)){
die("there are no stations available");
}
$fields=array_keys($stations[0]);
echo
"<h1> List of stations </h1>";
echo
"<table border=\"1\">";
echo
"<tr>";
foreach($fields as $f){
echo "<th> $f </th>";
}
echo
"</tr>";
foreach($stations as $row){
echo "<tr>";
foreach($row as $value){
echo "<td> $value </td>";
}
echo "</tr>";
}
echo
"</table>";
$soap_station = & New PesslSOAPStation();
$soap_station->station_name = $stations[0]['f_name'];
$soap_station->username = 'soap';
$soap_station->password = 'test';
$station_data = & $soap_station->PesslSOAPStationDataGetFirst() or
die("error reading weather data: ".$soap_station->error);
if(!count($station_data)){
die("there is no data available");
}
$fields=array_keys($station_data[0]);
echo
"<h1> First block of weather data of station
".$stations[0]['f_name']."</h1>";
echo
"<table border=\"1\">";
echo
"<tr>";
foreach($fields as $f){
echo "<th>";
if($f=="f_date"){
echo "Date/Time";
}else{
$sens_info=$soap_station->PesslSOAPGetInfoSensors($f);
echo $sens_info["f_name"]."
".$sens_info["f_aggr"]."<br/>[".$sens_info["f_unit"]."]";
}
echo "</th>";
}
echo
"</tr>";
foreach($station_data as $row){
echo "<tr>";
foreach($row as $value){
echo "<td>";
if($value){
echo $value;
}else{
echo " ";
}
echo "</td>";
}
echo "</tr>";
}
echo
"</table>";
?>
It is also available here
Except
weather data, there can be additional data, generated by fieldclimate modules,
like diesase modules, forecast, etc. This data has the same structure as
weather data and is represented in a form of additional sensors of the station.
It means that it can be read with SOAP interface without any modifications. You
simply read sensors and data of the station.
Try this
script.
<?php
require_once('class.pessl_soap.php');
$soap_stations = & new
PesslsoapStationList();
$soap_stations ->username =
'soap';
$soap_stations ->password =
'test';
$stations = &
$soap_stations->PesslSoapStationListAll() or
die("error reading
station list: ".$soap_stations->error);
if(!count($stations)){
die("there are no
stations available");
}
$soap_station = & New
PesslsoapStation();
$soap_station->station_name =
$stations[0]['f_name'];
$soap_station->username = 'soap';
$soap_station->password = 'test';
$soap_station->show_user_app=true;
$station_data = &
$soap_station->PesslsoapStationDataGetLast() or
die("error reading
weather data: ".$soap_station->error);
if(!count($station_data)){
die("there is no
data available");
}
$fields=array_keys($station_data[0]);
echo "<h1> Last block of
weather data with additional sensors of station
".$stations[0]['f_name']."</h1>";
echo "<table
border=\"1\">";
echo "<tr>";
foreach($fields as $f){
echo "<th>";
if($f=="f_date"){
echo
"Date/Time";
}else{
$sens_info=$soap_station->PesslsoapGetInfoSensors($f);
if(!$sens_info){
continue;
}
echo
$sens_info["f_name"]."
".$sens_info["f_aggr"]."<br/>[".$sens_info["f_unit"]."]";
}
echo
"</th>";
}
echo "</tr>";
foreach($station_data as $row){
echo
"<tr>";
foreach($row as $value){
echo
"<td>";
if($value){
echo
$value;
}else{
echo
" ";
}
echo
"</td>";
}
echo
"</tr>";
}
echo "</table>";
?>
This script is also available here station_data_user_app.php
You can see that that now station has much more
sensors than in previous examples. This is because we have requested not only
the weather data but also sensors generated by additional modules. This is done
by setting property show_user_app of soap_station class to true.
$soap_station->show_user_app=true;
What additional sensors the station
has depends on what modules are activated by the user. To activate/deactivate
modules log in into fieldclimate, go to user settings and click on “Activate
disease modules and forecast”. In you version it may have different text
depending on the language. In this example there are 2 additional modules:
apple disease and weather forecast, so the list of sensors looks like this
Date/Time |
Soil temperature
aver |
Soil temperature
min |
Soil temperature
max |
Relative
humidity aver |
Air temperature
aver |
Air temperature
min |
Air temperature
max |
Precipitation
sum |
Battery voltage
last |
Leaf Wetness
time |
Dew Point aver |
Dew Point min |
Asco max |
Asco Reif max |
Asco Frei max |
Asco Light
Infection max |
Asco Medium
Infection max |
Asco Strong
Infection max |
Conidia Light
Infection max |
Conidia Medium
Infection max |
Conidia Strong
Infection max |
Fireblight DIV
aver |
Temp Sum aver |
Blossomblight
aver |
temperature aver |
temperature min |
temperature max |
Total Precip.
sum |
convective
Precip sum |
Snow Fraction
aver |
Snow Fraction
max |
Low Clouds aver |
Low Clouds max |
Mid Clouds aver |
Mid Clouds max |
High Clouds aver |
High Clouds max |
Probability of
Precipitation aver |
Probability of
Precipitation max |
GUST aver |
GUST max |
wind speed aver |
wind speed max |
wind direction
aver |
wind direction
max |
relative
humidity aver |
relative
humidity max |
The only
problem here is that the data is only available until last weather data record,
though weather forecast should go in the future. This is because all additional
data is synchronized with the weather data. To change this behavior, so called
“master user application” has been introduced. It is stored in the
master_user_app property of soap_station class. This property defines, data of
which module has the highest priority. By default, it is weather data and data
of other applications is merged according to date/time of the weather data. It
also defines the behaviour of GetMinMaxDate() function. If a name of user
application is assigned to master_user_app, data generated by this application
is read first and data of other
applications is merged with it. Following values are defined for
master_user_app
1.
false
= weather data
2.
‘weather_data’
= weather data
3.
‘forecast’
= weather forecast
Now let’s
try the same script but with
$soap_station->master_user_app=’forecast’;
Script is also available here station_data_forecast.php
You can see that the data goes one week beyond
the last record of weather data thus allowing reading weather forecast. Please
note that normal sensors have null-values in the future. Care should be taken
for implementing replication solutions.
The library has been developed for PHP 4.x. It may
not work with PHP 5 due to name conflicts. Release of PHP 5 compatible version
is scheduled for April 2008.
After learning the basics of data interface you
can start developing your own applications. Here you will find a complete
example similar to fieldclimate web site working solely through data interface
described in this manual index.php .
You can download the
source code and use it as a skeleton for your development.
We hope you will find this interface useful.
Although it is read-only it opens up possibility to implement many different
applications without big efforts and expenses.
Please send error reports, suggestions,
requests for support and examples of your applications to software@metos.at