1 // metar interface class
3 // Written by Melchior FRANZ, started January 2005.
5 // Copyright (C) 2005 Melchior FRANZ - mfranz@aon.at
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 * Implements FGMetar class that inherits from SGMetar.
27 * o provide defaults for unset values
28 * o interpolate/randomize data (GREATER_THAN)
29 * o derive additional values (time, age, snow cover)
30 * o consider minimum identifier (CAVOK, mil. color codes)
33 * - NSC & mil. color codes
39 #include <simgear/math/sg_random.h>
40 #include <simgear/timing/sg_time.hxx>
41 #include <simgear/timing/lowleveltime.h>
43 #include <Main/fg_props.hxx>
45 #include "fgmetar.hxx"
48 FGMetar::FGMetar(const string& icao) :
55 // CAVOK: visibility >= 10km; lowest cloud layer >= 5000 ft; any coverage
57 if (_min_visibility.getVisibility_m() == SGMetarNaN)
58 _min_visibility.set(12000.0);
60 if (_max_visibility.getVisibility_m() == SGMetarNaN)
61 _min_visibility.set(12000.0);
63 vector<SGMetarCloud> cv = _clouds;;
66 cl.set(5500 * SG_FEET_TO_METER, SGMetarCloud::COVERAGE_SCATTERED);
67 _clouds.push_back(cl);
72 d = _min_visibility.getVisibility_m();
75 if (_min_visibility.getModifier() == SGMetarVisibility::GREATER_THAN)
76 d += 15000.0;// * sg_random();
77 _min_visibility.set(d);
79 if (_max_visibility.getVisibility_m() == SGMetarNaN)
80 _max_visibility.set(d);
82 for (i = 0; i < 8; i++) {
83 d = _dir_visibility[i].getVisibility_m();
85 _dir_visibility[i].set(10000.0);
86 if (_dir_visibility[i].getModifier() == SGMetarVisibility::GREATER_THAN)
87 d += 15000.0;// * sg_random();
88 _dir_visibility[i].set(d);
92 if (_wind_dir == -1) {
93 if (_wind_range_from == -1) {
98 _wind_dir = (_wind_range_from + _wind_range_to) / 2;
100 } else if (_wind_range_from == -1) {
101 _wind_range_from = _wind_range_to = _wind_dir;
104 if (_wind_speed == SGMetarNaN)
106 if (_gust_speed == SGMetarNaN)
110 vector<SGMetarCloud> cv = _clouds;
111 vector<SGMetarCloud>::iterator cloud, cv_end = cv.end();
113 for (i = 0, cloud = cv.begin(); cloud != cv_end; ++cloud, i++) {
114 SGMetarCloud::Coverage cov = cloud->getCoverage();
115 if (cov == SGMetarCloud::COVERAGE_NIL)
116 cov = SGMetarCloud::COVERAGE_CLEAR;
118 double alt = cloud->getAltitude_ft();
119 if (alt == SGMetarNaN)
122 cloud->set(alt, cov);
126 // temperature/pressure
127 if (_temp == SGMetarNaN)
130 if (_dewp == SGMetarNaN)
133 if (_pressure == SGMetarNaN)
134 _pressure = 30.0 * SG_INHG_TO_PA;
137 map<string, SGMetarRunway> rm = getRunways();
138 map<string, SGMetarRunway>::const_iterator runway, rm_end = rm.end();
139 for (runway = rm.begin(); runway != rm_end; ++runway) {
140 SGMetarRunway rwy = runway->second;
141 if (rwy.getDeposit() >= 3 ) {
146 if (_temp < 5.0 && _snow)
148 if (_temp < 1.0 && getRelHumidity() > 80)
151 _time = sgTimeGetGMT(_year - 1900, _month - 1, _day, _hour, _minute, 0);
153 SG_LOG(SG_ENVIRONMENT, SG_INFO, _data);
155 SG_LOG(SG_ENVIRONMENT, SG_INFO, "METAR from proxy");
157 SG_LOG(SG_ENVIRONMENT, SG_INFO, "METAR from weather.noaa.gov");
161 long FGMetar::getAge_min() const
163 time_t now = _x_proxy ? _rq_time : sgGMTime();
164 return (now - _time) / 60;