29#ifdef _USE_SYSTEM_JSONLIB
30#include <nlohmann/json.hpp>
48static size_t WriteCallback(
void *contents,
size_t size,
size_t nmemb,
void *userp)
50 ((std::string *)userp)->append((
char *)contents, size * nmemb);
58 owmLat = std::numeric_limits<double>::quiet_NaN();
59 owmLong = std::numeric_limits<double>::quiet_NaN();
60 previousForecast = std::numeric_limits<double>::quiet_NaN();
63 curl_global_init(CURL_GLOBAL_DEFAULT);
68 curl_global_cleanup();
73 return "OpenWeatherMap";
84 if (owmAPIKeyTP[0].isEmpty())
86 LOG_ERROR(
"OpenWeatherMap API Key is not available. Please register your API key at "
87 "www.openweathermap.org and save it under Options.");
103 char api_key[256] = {0};
105 owmAPIKeyTP[0].
fill(
"API_KEY",
"API Key", api_key);
109 addParameter(
"WEATHER_TEMPERATURE",
"Temperature (C)", -10, 30, 15);
110 addParameter(
"WEATHER_PRESSURE",
"Pressure (hPa)", 900, 1100, 15);
111 addParameter(
"WEATHER_HUMIDITY",
"Humidity (%)", 0, 100, 15);
112 addParameter(
"WEATHER_WIND_SPEED",
"Wind (m/s)", 0, 20, 15);
113 addParameter(
"WEATHER_RAIN_HOUR",
"Rain precip (mm)", 0, 0, 15);
114 addParameter(
"WEATHER_SNOW_HOUR",
"Snow precip (mm)", 0, 0, 15);
115 addParameter(
"WEATHER_CLOUD_COVER",
"Clouds (%)", 0, 100, 15);
116 addParameter(
"WEATHER_CODE",
"Status code", 200, 810, 15);
135 owmAPIKeyTP.
update(texts, names, n);
151 owmLong = (longitude > 180) ? (longitude - 360) : longitude;
158 CURL *curl {
nullptr};
160 std::string readBuffer;
161 char errorBuffer[CURL_ERROR_SIZE] = {0};
162 char requestURL[
MAXRBUF] = {0};
165 if (std::isnan(owmLat) || std::isnan(owmLong))
170 snprintf(requestURL,
MAXRBUF,
"http://api.openweathermap.org/data/2.5/weather?lat=%g&lon=%g&appid=%s&units=metric",
171 owmLat, owmLong, owmAPIKeyTP[0].
getText());
173 curl = curl_easy_init();
176 curl_easy_setopt(curl, CURLOPT_URL, requestURL);
177 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
178 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
179 curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
181 res = curl_easy_perform(curl);
182 curl_easy_cleanup(curl);
185 if(strlen(errorBuffer))
187 LOGF_ERROR(
"Error %d reading data: %s", res, errorBuffer);
191 LOGF_ERROR(
"Error %d reading data: %s", res, curl_easy_strerror(res));
206 std::string description;
210 json weatherReport = json::parse(readBuffer);
212 weatherReport[
"weather"][0][
"id"].
get_to(code);
213 weatherReport[
"weather"][0][
"description"].
get_to(description);
215 if (code >= 200 && code < 300)
220 else if (code >= 300 && code < 400)
225 else if (code >= 500 && code < 700)
230 else if (code >= 700 && code < 800)
235 else if (code == 800)
240 else if (code >= 801 && code <= 803)
245 else if (code >= 804 && code < 900)
254 weatherReport[
"main"][
"pressure"].
get_to(pressure);
258 weatherReport[
"wind"][
"speed"].
get_to(wind);
260 weatherReport[
"clouds"][
"all"].
get_to(clouds);
264 if (weatherReport[
"rain"].contains(
"h"))
266 weatherReport[
"rain"][
"h"].
get_to(rain);
268 else if (weatherReport[
"rain"].contains(
"1h"))
270 weatherReport[
"rain"][
"1h"].
get_to(rain);
276 if (weatherReport[
"snow"].contains(
"h"))
278 weatherReport[
"snow"][
"h"].
get_to(snow);
280 else if (weatherReport[
"snow"].contains(
"1h"))
282 weatherReport[
"snow"][
"1h"].
get_to(snow);
295 if (std::isnan(previousForecast) || forecast != previousForecast)
297 LOGF_INFO(
"Forecast changed: %s (Code: %d)", description.c_str(), code);
298 previousForecast = forecast;
317 owmAPIKeyTP.
save(fp);
INDI::PropertyText getText(const char *name) const
virtual bool saveConfig(bool silent=false, const char *property=nullptr)
Save the current properties in a configuration file.
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
void defineProperty(INumberVectorProperty *property)
void addDebugControl()
Add Debug control to the driver.
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
void save(FILE *f) const
save Save property to configuration file.
const char * getName() const
bool isNameMatch(const char *otherName) const
bool update(const char *const texts[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
void addParameter(std::string name, std::string label, double numMinOk, double numMaxOk, double percWarning, bool flipWarning=false)
Add a physical weather measurable parameter to the weather driver.
bool setCriticalParameter(std::string name)
setCriticalParameter Set parameter that is considered critical to the operation of the observatory....
void setParameterValue(std::string name, double value)
setParameterValue Update weather parameter value
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
virtual void ISGetProperties(const char *dev) override
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
INDI::PropertyNumber LocationNP
void setWeatherConnection(const uint8_t &value)
setWeatherConnection Set Weather connection mode. Child class should call this in the constructor bef...
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
virtual void ISGetProperties(const char *dev) override
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
virtual bool updateLocation(double latitude, double longitude, double elevation) override
Update weather station location.
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
bool Connect() override
Connect to the device. INDI::DefaultDevice implementation connects to appropriate connection interfac...
const char * getDefaultName() override
virtual IPState updateWeather() override
updateWeather Update weather conditions from device or service. The function should not change the st...
bool Disconnect() override
Disconnect from device.
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
virtual ~OpenWeatherMap()
a class to store JSON values
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
general exception of the basic_json class
const int id
the id of the exception
const char * what() const noexcept override
returns the explanatory string
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
int IUGetConfigText(const char *dev, const char *property, const char *member, char *value, int len)
IUGetConfigText Opens configuration file and reads single text property.
#define LOGF_INFO(fmt,...)
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
#define LOGF_ERROR(fmt,...)
basic_json<> json
default specialization
std::unique_ptr< OpenWeatherMap > openWeatherMap(new OpenWeatherMap())