FlightGear next
fgmetar.cxx
Go to the documentation of this file.
1/*
2 * SPDX-FileName: fgmetar.cxx
3 * SPDX-FileComment: metar interface class
4 * SPDX-FileCopyrightText: Copyright (C) 2005 Melchior FRANZ - mfranz@aon.at
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24#include <simgear/math/sg_random.hxx>
25#include <simgear/timing/sg_time.hxx>
26#include <simgear/timing/lowleveltime.h>
27
28#include <Main/fg_props.hxx>
29
30#include "fgmetar.hxx"
31
32const double CAVOK_VISIBILITY = 9999.0;
33
34FGMetar::FGMetar(const std::string& icao) :
35 SGMetar(icao),
36 _snow_cover(false)
37{
38 int i;
39 double d;
40
41 // CAVOK: visibility >= 10km; lowest cloud layer >= 5000 ft; any coverage
42 if (getCAVOK()) {
43 if (_min_visibility.getVisibility_m() == SGMetarNaN)
44 _min_visibility.set(CAVOK_VISIBILITY);
45
46 if (_max_visibility.getVisibility_m() == SGMetarNaN)
47 _min_visibility.set(CAVOK_VISIBILITY);
48
49 std::vector<SGMetarCloud> cv = _clouds;;
50 if (cv.empty()) {
51 SGMetarCloud cl;
52 cl.set(5500 * SG_FEET_TO_METER, SGMetarCloud::COVERAGE_SCATTERED);
53 _clouds.push_back(cl);
54 }
55 }
56
57 // visibility
58 d = _min_visibility.getVisibility_m();
59 if (d == SGMetarNaN)
60 d = 10000.0;
61 if (_min_visibility.getModifier() == SGMetarVisibility::GREATER_THAN)
62 d += 15000.0;// * sg_random();
63 _min_visibility.set(d);
64
65 if (_max_visibility.getVisibility_m() == SGMetarNaN)
66 _max_visibility.set(d);
67
68 for (i = 0; i < 8; i++) {
69 d = _dir_visibility[i].getVisibility_m();
70 if (d == SGMetarNaN)
71 _dir_visibility[i].set(10000.0);
72 if (_dir_visibility[i].getModifier() == SGMetarVisibility::GREATER_THAN)
73 d += 15000.0;// * sg_random();
74 _dir_visibility[i].set(d);
75 }
76
77 // wind
78 if (_wind_dir == -1) {
79 if (_wind_range_from == -1) {
80 _wind_dir = 0;
81 _wind_range_from = 0;
82 _wind_range_to = 359;
83 } else {
84 _wind_dir = (_wind_range_from + _wind_range_to) / 2;
85 }
86 } else if (_wind_range_from == -1) {
87 _wind_range_from = _wind_range_to = _wind_dir;
88 }
89
90 if (_wind_speed == SGMetarNaN)
91 _wind_speed = 0.0;
92 if (_gust_speed == SGMetarNaN)
93 _gust_speed = 0.0;
94
95 // clouds
96 std::vector<SGMetarCloud> cv = _clouds;
97 std::vector<SGMetarCloud>::iterator cloud, cv_end = cv.end();
98
99 for (i = 0, cloud = cv.begin(); cloud != cv_end; ++cloud, i++) {
100 SGMetarCloud::Coverage cov = cloud->getCoverage();
101 if (cov == SGMetarCloud::COVERAGE_NIL)
102 cov = SGMetarCloud::COVERAGE_CLEAR;
103
104 double alt = cloud->getAltitude_ft();
105 if (alt == SGMetarNaN)
106 alt = -9999;
107
108 cloud->set(alt, cov);
109 }
110
111
112 // temperature/pressure
113 if (_temp == SGMetarNaN)
114 _temp = 15.0;
115
116 if (_dewp == SGMetarNaN)
117 _dewp = 0.0;
118
119 if (_pressure == SGMetarNaN)
120 _pressure = 30.0 * SG_INHG_TO_PA;
121
122 // snow cover
123 std::map<std::string, SGMetarRunway> rm = getRunways();
124 std::map<std::string, SGMetarRunway>::const_iterator runway, rm_end = rm.end();
125 for (runway = rm.begin(); runway != rm_end; ++runway) {
126 SGMetarRunway rwy = runway->second;
127 if (rwy.getDeposit() >= 3 ) {
128 _snow_cover = true;
129 break;
130 }
131 }
132 if (_temp < 5.0 && _snow)
133 _snow_cover = true;
134 if (_temp < 1.0 && getRelHumidity() > 80)
135 _snow_cover = true;
136
137 _time = sgTimeGetGMT(_year - 1900, _month - 1, _day, _hour, _minute, 0);
138
139 SG_LOG(SG_ENVIRONMENT, SG_DEBUG, "FGMetar:" << getDataString());
140 if (_x_proxy)
141 SG_LOG(SG_ENVIRONMENT, SG_DEBUG, "METAR from proxy");
142 else
143 SG_LOG(SG_ENVIRONMENT, SG_DEBUG, "METAR from tgftp.nws.noaa.gov");
144}
145
146
148{
149 time_t now = _x_proxy ? _rq_time : time(nullptr);
150 return (now - _time) / 60;
151}
152
#define i(x)
FGMetar(const std::string &icao)
Definition fgmetar.cxx:34
long getAge_min() const
Definition fgmetar.cxx:147
const double CAVOK_VISIBILITY
Definition fgmetar.cxx:32