FMI avoin data beta ja sen kokeilut

Aloittaja weatherc, torstai, 28.02.2013, 15:25

« edellinen - seuraava »

0 Jäsenet ja 1 Vieras katselee tätä aihetta.

weatherc

Pitääpi seurailla mitä tuonne Githubiin ilmestyy ;D

Jouzer

Tervehdys! Ajattelin kysyä täältä neuvoa enkä hakata päätä puuhun enää pidempään tän asian kanssa.

Eli tarkoitus olisi tehdä serverille pyörimään ohjelma, joka hakee lämpötilaennustuksen Ilmatieteen Laitoksen avoin data palvelusta x ajan päähän, parsii siitä sen tarvittavan tiedon ja tallentaa sen arvon ASCIIna esim. tekstitiedostoon.

Onko jotain ehdotuksia miten tää toteutus menisi? Löytyisikö noista GitHubin resursseista joku melko valmis ratkaisu? Katselin tuota edellä jaettua php scriptiä ja GitHubissa näytti olevan muutama C++ kirjoitettu ohjelma, mutta kun en niistä oikein tiedä mikä on se resurssi mitä kannattaisi käyttää tähän hommaan.

weatherc

Tervehdys, ja tervetuloa foorumille!

Ihan ensimmäiseksi, kuinka pitkän ajan päähän haluat ennustetta?
FMI:n avoimessa datassa ei ole kuin 48h (52h max riippuen ajankohdasta). Sitä pidemmälle mentäessä on melkein turvauduttava YR.no:n XML-tiedostoihin:
http://api.yr.no/weatherapi/locationforecast/1.9/?lat=61&lon=24

Jouzer

Kiitti!

48h riittää mainiosti. Data on kyllä varmasti sopivaa, pitäisi vaan saada kone automaattisesti hakemaan ja parsimaan ja tallentamaan  tarpeellinen data asciiksi.  Oisko antaa vinkkejä?

weatherc

Ei oikeen muuta kun koittaa löytää xml-parseri haluamalle kielelle. Tuossa pikainen PHP:lle joka palauttaa kaikki arvot $yrfr-arrayssä:


<?php
$cit
="Paikkakunta";
URL 'http://data.fmi.fi/fmi-apikey/API-AVAIN-TÄHÄN/wfs?request=getFeature&storedquery_id=fmi::forecast::hirlam::surface::point::timevaluepair&timestep=60&crs=EPSG::4326&place='.fixurl($cit);
$root "/fmi/cache/";
$cacheName $root.'fmifrcst_'.md5($cit).'.txt';  // prototype for path/filename for cache file
$fetchSeconds 3600;  // refresh every hour

if (file_exists($cacheName) and filemtime($cacheName) + $fetchSeconds time()) {
  
$html file_get_contents($cacheName);
} else {
  
$html file_get_contents($URL);
  
file_put_contents($cacheName,$html);;
}

$xml=xml2array($html);
//print_r($xml);
$xml $xml["wfs:FeatureCollection"]["wfs:member"]; 
  
for(
$i=0;$i<count($xml);$i++){
  if(
$i==0){
    
$place $xml[$i]["omso:PointTimeSeriesObservation"]["om:featureOfInterest"]["sams:SF_SpatialSamplingFeature"]["sams:shape"]["gml:MultiPoint"]["gml:pointMembers"]["gml:Point"][1]["gml:name"];
    
$coords $xml[$i]["omso:PointTimeSeriesObservation"]["om:featureOfInterest"]["sams:SF_SpatialSamplingFeature"]["sams:shape"]["gml:MultiPoint"]["gml:pointMembers"]["gml:Point"]["gml:pos"];
    
$frctime $xml[$i]["omso:PointTimeSeriesObservation"]["om:resultTime"]["gml:TimeInstant"]["gml:timePosition"];
  }
    
  
$id $xml[$i]["omso:PointTimeSeriesObservation"]["om:result"]["wml2:MeasurementTimeseries_attr"]["gml:id"];
  
$id str_replace("1-1-","",$id);
  
$vals $xml[$i]["omso:PointTimeSeriesObservation"]["om:result"]["wml2:MeasurementTimeseries"]["wml2:point"];
  for(
$t=0;$t<count($vals);$t++) {
    
$line $vals[$t];
    if(
$i==0){$yrfr[times][] = strtotime($line["wml2:MeasurementTVP"]["wml2:time"]);}
    
$yrfr[$id][] = $line["wml2:MeasurementTVP"]["wml2:value"];
  }
}
//print_r($yrfr);

function xml2array($contents$get_attributes=1$priority 'tag') {
    if(!
$contents) return array();

    if(!
function_exists('xml_parser_create')) {
        
//print "'xml_parser_create()' function not found!";
        
return array();
    }

    
//Get the XML parser of PHP - PHP must have this module for the parser to work
    
$parser xml_parser_create('');
    
xml_parser_set_option($parserXML_OPTION_TARGET_ENCODING"UTF-8"); # http://minutillo.com/steve/weblog/2004/6/17/php-xml-and-character-encodings-a-tale-of-sadness-rage-and-data-loss
    
xml_parser_set_option($parserXML_OPTION_CASE_FOLDING0);
    
xml_parser_set_option($parserXML_OPTION_SKIP_WHITE1);
    
xml_parse_into_struct($parsertrim($contents), $xml_values);
    
xml_parser_free($parser);

    if(!
$xml_values) return;//Hmm...

    //Initializations
    
$xml_array = array();
    
$parents = array();
    
$opened_tags = array();
    
$arr = array();

    
$current = &$xml_array//Refference

    //Go through the tags.
    
$repeated_tag_index = array();//Multiple tags with same name will be turned into an array
    
foreach($xml_values as $data) {
        unset(
$attributes,$value);//Remove existing values, or there will be trouble

        //This command will extract these variables into the foreach scope
        // tag(string), type(string), level(int), attributes(array).
        
extract($data);//We could use the array by itself, but this cooler.

        
$result = array();
        
$attributes_data = array();
        
        if(isset(
$value)) {
            if(
$priority == 'tag'$result $value;
            else 
$result['value'] = $value//Put the value in a assoc array if we are in the 'Attribute' mode
        
}

        
//Set the attributes too.
        
if(isset($attributes) and $get_attributes) {
            foreach(
$attributes as $attr => $val) {
                if(
$priority == 'tag'$attributes_data[$attr] = $val;
                else 
$result['attr'][$attr] = $val//Set all the attributes in a array called 'attr'
            
}
        }

        
//See tag status and do the needed.
        
if($type == "open") {//The starting of the tag '<tag>'
            
$parent[$level-1] = &$current;
            if(!
is_array($current) or (!in_array($tagarray_keys($current)))) { //Insert New tag
                
$current[$tag] = $result;
                if(
$attributes_data$current[$tag'_attr'] = $attributes_data;
                
$repeated_tag_index[$tag.'_'.$level] = 1;

                
$current = &$current[$tag];

            } else { 
//There was another element with the same tag name

                
if(isset($current[$tag][0])) {//If there is a 0th element it is already an array
                    
$current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;
                    
$repeated_tag_index[$tag.'_'.$level]++;
                } else {
//This section will make the value an array if multiple tags with the same name appear together
                    
$current[$tag] = array($current[$tag],$result);//This will combine the existing item and the new item together to make an array
                    
$repeated_tag_index[$tag.'_'.$level] = 2;
                    
                    if(isset(
$current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well
                        
$current[$tag]['0_attr'] = $current[$tag.'_attr'];
                        unset(
$current[$tag.'_attr']);
                    }

                }
                
$last_item_index $repeated_tag_index[$tag.'_'.$level]-1;
                
$current = &$current[$tag][$last_item_index];
            }

        } elseif(
$type == "complete") { //Tags that ends in 1 line '<tag />'
            //See if the key is already taken.
            
if(!isset($current[$tag])) { //New Key
                
$current[$tag] = $result;
                
$repeated_tag_index[$tag.'_'.$level] = 1;
                if(
$priority == 'tag' and $attributes_data$current[$tag'_attr'] = $attributes_data;

            } else { 
//If taken, put all things inside a list(array)
                
if(isset($current[$tag][0]) and is_array($current[$tag])) {//If it is already an array...

                    // ...push the new element into that array.
                    
$current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;
                    
                    if(
$priority == 'tag' and $get_attributes and $attributes_data) {
                        
$current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
                    }
                    
$repeated_tag_index[$tag.'_'.$level]++;

                } else { 
//If it is not an array...
                    
$current[$tag] = array($current[$tag],$result); //...Make it an array using using the existing value and the new value
                    
$repeated_tag_index[$tag.'_'.$level] = 1;
                    if(
$priority == 'tag' and $get_attributes) {
                        if(isset(
$current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well
                            
                            
$current[$tag]['0_attr'] = $current[$tag.'_attr'];
                            unset(
$current[$tag.'_attr']);
                        }
                        
                        if(
$attributes_data) {
                            
$current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
                        }
                    }
                    
$repeated_tag_index[$tag.'_'.$level]++; //0 and 1 index is already taken
                
}
            }

        } elseif(
$type == 'close') { //End of tag '</tag>'
            
$current = &$parent[$level-1];
        }
    }
    
    return(
$xml_array);
}

Jouzer

Vau, no kiitos. Pitää tutustua ajan kanssa. Onko toi ihan toimiva pätkä vai enemmänki periaate?
XML parseri mul itseasias on jo sille kohdekielelle, et yks vaihtoehto olisi se että parsis siellä purkissa minne data on tarkoitus saada. No, nää ratkee kyllä, lähinnä ajattelin miten tuo data haetaan automaattisesti kun kaikki web-koodaus on aika tuntematonta mulle mutta aika näppärästi se näyttäs menevän jos tollasella pätkällä selviää. Kiitos!

weatherc

Lainaus käyttäjältä: Jouzer - keskiviikko, 07.06.2017, 15:47
Vau, no kiitos. Pitää tutustua ajan kanssa. Onko toi ihan toimiva pätkä vai enemmänki periaate?

Ihan toimiva, nappasin sen skripistä joka raksuttaa tuota FMIennuste-sivua nordicweatherissä. :)

Jos koordinaatit ovat helpompia eikä jaksa metsästää sopivaa paikkakuntaa niin sen ennusteen voi myös hakea niillä:

http://data.fmi.fi/fmi-apikey/API-AVAIN-TÄHÄN/wfs?request=getFeature&storedquery_id=fmi::forecast::hirlam::surface::point::timevaluepair&timestep=60&&crs=EPSG::4326&latlon=$lat,$lon

Jouzer

#97
Tervehdys taas! Nyt saatiin aikaiseksi tehdä tuo ohjelma mikä lataa ja parsii tuon xml:än ja sain sen jopa toimimaan.

Ongelma on nyt vaan, kun en sääennustuksista juuri mitään tiedä, on ymmärtää mitä mikäkin arvo tarkoittaa. Jos joku tietäväinen viittisi tähän vastata niin varmaan hyödyttäisi kaikkia ilmatieteen laitoksen dataa käyttäviä koska en tunnin googletuksella saanut näihin selvyyttä. :D Täytän tähän ne mitkä itse tiedän.

Selite (yksikkö)

Temperature = Lämpötila (celcius)
Pressure = Ilmanpaine (pa)
Humidity = Ilmankosteus (%)
WindDirection = Tuulen suunta. (Onkohan tässä toi numero asteluku jossa pohjoinen on 0 astetta..?)
WindSpeedMS = Tuulen nopeus (m/s)
WindUMS = U-component of wind vector (Voidaan laskea tuulen nopeus ja suunta)
WindVMS = V-component of wind vector  ^
MaximumWind = Maksimituuli (m/s)
WindGust = Puuskatuuli (m/s)
DewPoint = Kastepiste-lämpötila (celcius)
TotalCloudCover = Pilvien peittävyys (%)
WeatherSymbol3 = Tähän tulee http://ilmatieteenlaitos.fi/latauspalvelun-pikaohje tuolta taulukosta löytyvä sääikonia vastaava numero
LowCloudCover = Pilvien peittävyys matalalla (%?)
MediumCloudCover = Pilvien peittävyys keskivaiheilla (%?)
HighCloudCover = Pilvien peittävyys korkealla (%?)   ^  Ei tietoa korkeuksista
Precipitation1h = Sateen määrä tunnissa ("mm" eli l/m2 ?)
PrecipitationAmount = Sademäärä, ei tietoa aikajaksosta
RadiationGlobalAccumulation = (J/m2/1s)
RadiationLWAccumulation = Pitkäaaltoinen kumuloitu säteily (J/m2/1s)
RadiationNetSurfaceLWAccumulation = Pitkäaaltoinen (Infrapuna, "lämpö") maanpinnan kumuloitu netto (J/m2/1s) http://www.earthonlinemedia.com/ebooks/tpe_3e/energy/longwave_radiation.html
RadiationNetSurfaceSWAccumulation = Lyhytaaltoinen (valo, UV) maanpinnan kumuloitu netto (J/m2/1s)
RadiationDiffuseAccumulation = "Taittunut säteily" tjsp. https://en.wikipedia.org/wiki/Diffuse_sky_radiation

No, te varmaan tiedätte nämä, täytin vaan ne mistä olin olevinaan varma.
Muokkaan tän postin kuntoon sitte jos saadaan taulukkoon täytettä. Kiitos!

weatherc

XML-filussa löytyy osoitteet selityksiin jokaisen parametrin kohdalla, esim WindUMS:
<om:observedProperty xlink:href="http://data.fmi.fi/fmi-apikey/API-AVAIN/meta?observableProperty=forecast&param=WindUMS&language=eng"/>
joka kertoo että : U-component of wind vector

WindUMS:lla + WindVMS:llä saa laskettua sekä tulen nopeuden että suunnan.

Jouzer

Näköjään! Tosin ilman tuota viimeistä lausettasi asia ei olisi auennut (minulle). Yritin katsella kaikkia mitä tuossa HIRLAM(?) xml:ssä on, mutta esimerkiksi noi Radiation hommia ei ole juurikaan selitellyt. Tarvisi siis itse tietää näistä vastaako joku Forecan "Auringon säteilyn vaikutus w/m2" arvoa, mutta olisi varmaan hyvä myös jos internetissä olisi lista asian kanssa puuhaaville.

Katselin myös muita ja selitteet on kyllä sen verran lyhytsanaisia että ei-harrastajalle ei varmaan aukene. Ajattelin, että tämä voisi olla hyvä paikka kasata lista myös tuleville tiedonetsijöille.
No kiitos nyt kuitenkin neuvosta!