v.0.3.0 Library WeatherData
This commit is contained in:
7
lib/WeatherData/library.json
Normal file
7
lib/WeatherData/library.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "BlinkLed",
|
||||
"version": "1.0.0",
|
||||
"description": "A simple LED control library with internal LED helper.",
|
||||
"authors": [{ "name": "TiiJay14" }],
|
||||
"frameworks": "arduino"
|
||||
}
|
||||
187
lib/WeatherData/src/WeatherFetcher.cpp
Normal file
187
lib/WeatherData/src/WeatherFetcher.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
#include "WeatherFetcher.h"
|
||||
#include <WiFi.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#include <ColorSerial.h>
|
||||
|
||||
WeatherFetcher::WeatherFetcher(const char *api_key) : API_KEY(api_key) {}
|
||||
|
||||
bool WeatherFetcher::connectToWiFi(const char *ssid, const char *password)
|
||||
{
|
||||
ColorSerial::info("Verbinde mit WiFi: ");
|
||||
ColorSerial::info(ssid);
|
||||
|
||||
WiFi.begin(ssid, password);
|
||||
|
||||
int attempts = 0;
|
||||
while (WiFi.status() != WL_CONNECTED && attempts < 20)
|
||||
{
|
||||
delay(1000);
|
||||
ColorSerial::info(".");
|
||||
attempts++;
|
||||
}
|
||||
|
||||
ColorSerial::wifiStatus();
|
||||
|
||||
return WiFi.status() == WL_CONNECTED;
|
||||
}
|
||||
|
||||
Weather WeatherFetcher::actual_weather(const char *city, const char *lang, bool test_mode)
|
||||
{
|
||||
if (test_mode)
|
||||
{
|
||||
return create_test_weather();
|
||||
}
|
||||
|
||||
if (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
Serial.println("Keine WiFi Verbindung!");
|
||||
return weather;
|
||||
}
|
||||
|
||||
String weather_url =
|
||||
"https://api.weatherapi.com/v1/current.json?key=" + String(API_KEY) +
|
||||
"&q=" + String(city) + "&aqi=yes&lang=" + String(lang);
|
||||
|
||||
Serial.println("Hole Wetterdaten von: " + weather_url);
|
||||
|
||||
String json_data = fetch_from_url(weather_url);
|
||||
|
||||
if (!json_data.isEmpty())
|
||||
{
|
||||
weather = parse_weather_json(json_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Fehler beim Abrufen der Wetterdaten!");
|
||||
}
|
||||
|
||||
return weather;
|
||||
}
|
||||
|
||||
String WeatherFetcher::fetch_from_url(const String &url)
|
||||
{
|
||||
HTTPClient http;
|
||||
String payload = "";
|
||||
|
||||
http.begin(url);
|
||||
http.setTimeout(10000);
|
||||
|
||||
int httpCode = http.GET();
|
||||
|
||||
if (httpCode == HTTP_CODE_OK)
|
||||
{
|
||||
payload = http.getString();
|
||||
Serial.println("Daten erfolgreich empfangen");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.printf("HTTP Fehler: %d\n", httpCode);
|
||||
Serial.println(http.errorToString(httpCode));
|
||||
}
|
||||
|
||||
http.end();
|
||||
return payload;
|
||||
}
|
||||
|
||||
Weather WeatherFetcher::parse_weather_json(const String &json_data)
|
||||
{
|
||||
Weather weather;
|
||||
|
||||
const size_t capacity = JSON_OBJECT_SIZE(20) + JSON_OBJECT_SIZE(10) + JSON_OBJECT_SIZE(15) + 2048;
|
||||
DynamicJsonDocument doc(capacity);
|
||||
|
||||
DeserializationError error = deserializeJson(doc, json_data);
|
||||
|
||||
if (error)
|
||||
{
|
||||
Serial.print("JSON Parsing fehlgeschlagen: ");
|
||||
Serial.println(error.c_str());
|
||||
return weather;
|
||||
}
|
||||
|
||||
// Location Daten parsen - jetzt direkt mit Arduino String
|
||||
if (doc.containsKey("location"))
|
||||
{
|
||||
JsonObject location = doc["location"];
|
||||
weather.location.name = location["name"].as<String>();
|
||||
weather.location.region = location["region"].as<String>();
|
||||
weather.location.country = location["country"].as<String>();
|
||||
weather.location.localtime = location["localtime"].as<String>();
|
||||
}
|
||||
|
||||
// Current Condition Daten parsen
|
||||
if (doc.containsKey("current"))
|
||||
{
|
||||
JsonObject current = doc["current"];
|
||||
weather.current.last_updated = current["last_updated"].as<String>();
|
||||
weather.current.temp_c = current["temp_c"].as<float>();
|
||||
weather.current.is_day = current["is_day"].as<int>();
|
||||
weather.current.wind_kph = current["wind_kph"].as<float>();
|
||||
weather.current.wind_dir = current["wind_dir"].as<String>();
|
||||
weather.current.pressure_mb = current["pressure_mb"].as<float>();
|
||||
weather.current.humidity = current["humidity"].as<int>();
|
||||
weather.current.cloud = current["cloud"].as<int>();
|
||||
weather.current.feelslike_c = current["feelslike_c"].as<float>();
|
||||
|
||||
// Condition Daten parsen
|
||||
if (current.containsKey("condition"))
|
||||
{
|
||||
JsonObject condition = current["condition"];
|
||||
weather.current.condition.text = condition["text"].as<String>();
|
||||
weather.current.condition.icon = condition["icon"].as<String>();
|
||||
}
|
||||
|
||||
// Air Quality Daten parsen
|
||||
if (current.containsKey("air_quality"))
|
||||
{
|
||||
JsonObject air_quality = current["air_quality"];
|
||||
weather.current.air_quality.co = air_quality["co"].as<float>();
|
||||
weather.current.air_quality.no2 = air_quality["no2"].as<float>();
|
||||
weather.current.air_quality.o3 = air_quality["o3"].as<float>();
|
||||
weather.current.air_quality.so2 = air_quality["so2"].as<float>();
|
||||
weather.current.air_quality.pm2_5 = air_quality["pm2_5"].as<float>();
|
||||
weather.current.air_quality.pm10 = air_quality["pm10"].as<float>();
|
||||
weather.current.air_quality.us_epa_index = air_quality["us-epa-index"].as<int>();
|
||||
weather.current.air_quality.gb_defra_index = air_quality["gb-defra-index"].as<int>();
|
||||
}
|
||||
}
|
||||
|
||||
Serial.println("Wetterdaten erfolgreich geparsed");
|
||||
return weather;
|
||||
}
|
||||
|
||||
Weather WeatherFetcher::create_test_weather()
|
||||
{
|
||||
Weather test_weather;
|
||||
|
||||
test_weather.location.name = "Grosshansdorf";
|
||||
test_weather.location.region = "Schleswig-Holstein";
|
||||
test_weather.location.country = "Germany";
|
||||
test_weather.location.localtime = "2023-10-01 12:30";
|
||||
|
||||
test_weather.current.last_updated = "2023-10-01 12:30";
|
||||
test_weather.current.temp_c = 15.5;
|
||||
test_weather.current.is_day = 1;
|
||||
test_weather.current.condition.text = "Sonnig";
|
||||
test_weather.current.condition.icon = "//cdn.weatherapi.com/weather/64x64/day/113.png";
|
||||
test_weather.current.wind_kph = 12.3;
|
||||
test_weather.current.wind_dir = "NW";
|
||||
test_weather.current.pressure_mb = 1013.0;
|
||||
test_weather.current.humidity = 65;
|
||||
test_weather.current.cloud = 10;
|
||||
test_weather.current.feelslike_c = 15.2;
|
||||
|
||||
test_weather.current.air_quality.co = 250.0;
|
||||
test_weather.current.air_quality.no2 = 12.5;
|
||||
test_weather.current.air_quality.o3 = 45.2;
|
||||
test_weather.current.air_quality.so2 = 2.1;
|
||||
test_weather.current.air_quality.pm2_5 = 8.5;
|
||||
test_weather.current.air_quality.pm10 = 12.3;
|
||||
test_weather.current.air_quality.us_epa_index = 1;
|
||||
test_weather.current.air_quality.gb_defra_index = 2;
|
||||
|
||||
Serial.println("Test-Wetterdaten generiert");
|
||||
return test_weather;
|
||||
}
|
||||
27
lib/WeatherData/src/WeatherFetcher.h
Normal file
27
lib/WeatherData/src/WeatherFetcher.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef WEATHER_FETCHER_H
|
||||
#define WEATHER_FETCHER_H
|
||||
|
||||
#include "WeatherStructs.h"
|
||||
#include <WiFi.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class WeatherFetcher
|
||||
{
|
||||
private:
|
||||
Weather weather;
|
||||
const char *API_KEY;
|
||||
|
||||
public:
|
||||
WeatherFetcher(const char *api_key);
|
||||
bool connectToWiFi(const char *ssid, const char *password);
|
||||
Weather actual_weather(const char *city = "grosshansdorf",
|
||||
const char *lang = "de",
|
||||
bool test_mode = false);
|
||||
|
||||
private:
|
||||
String fetch_from_url(const String &url);
|
||||
Weather parse_weather_json(const String &json_data);
|
||||
Weather create_test_weather();
|
||||
};
|
||||
|
||||
#endif
|
||||
53
lib/WeatherData/src/WeatherStructs.h
Normal file
53
lib/WeatherData/src/WeatherStructs.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#ifndef WEATHERSTRUCTS_H
|
||||
#define WEATHERSTRUCTS_H
|
||||
|
||||
#include <optional>
|
||||
|
||||
struct Location
|
||||
{
|
||||
String name = "";
|
||||
String region = "";
|
||||
String country = "";
|
||||
String localtime = "";
|
||||
};
|
||||
|
||||
struct Condition
|
||||
{
|
||||
std::optional<String> text;
|
||||
std::optional<String> icon;
|
||||
};
|
||||
|
||||
struct AirQuality
|
||||
{
|
||||
double co = 0.0;
|
||||
double no2 = 0.0;
|
||||
double o3 = 0.0;
|
||||
double so2 = 0.0;
|
||||
double pm2_5 = 0.0;
|
||||
double pm10 = 0.0;
|
||||
int us_epa_index = 0;
|
||||
int gb_defra_index = 0;
|
||||
};
|
||||
|
||||
struct CurrentCondition
|
||||
{
|
||||
String last_updated;
|
||||
double temp_c = 0.0;
|
||||
int is_day = 0;
|
||||
Condition condition;
|
||||
double wind_kph = 0.0;
|
||||
String wind_dir;
|
||||
double pressure_mb = 0.0;
|
||||
int humidity = 0;
|
||||
int cloud = 0;
|
||||
double feelslike_c = 0.0;
|
||||
AirQuality air_quality;
|
||||
};
|
||||
|
||||
struct Weather
|
||||
{
|
||||
Location location;
|
||||
CurrentCondition current;
|
||||
};
|
||||
|
||||
#endif
|
||||
57
restapi/mock-weather.json
Normal file
57
restapi/mock-weather.json
Normal file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"location": {
|
||||
"name": "Grosshansdorf",
|
||||
"region": "Schleswig-Holstein",
|
||||
"country": "Germany",
|
||||
"lat": 53.6667,
|
||||
"lon": 10.2833,
|
||||
"tz_id": "Europe/Berlin",
|
||||
"localtime_epoch": 1761383733,
|
||||
"localtime": "2025-10-25 11:15"
|
||||
},
|
||||
"current": {
|
||||
"last_updated_epoch": 1761383700,
|
||||
"last_updated": "2025-10-25 11:15",
|
||||
"temp_c": 10.2,
|
||||
"temp_f": 50.4,
|
||||
"is_day": 1,
|
||||
"condition": {
|
||||
"text": "Overcast",
|
||||
"icon": "//cdn.weatherapi.com/weather/64x64/day/122.png",
|
||||
"code": 1009
|
||||
},
|
||||
"wind_mph": 17.7,
|
||||
"wind_kph": 28.4,
|
||||
"wind_degree": 208,
|
||||
"wind_dir": "SSW",
|
||||
"pressure_mb": 991.0,
|
||||
"pressure_in": 29.26,
|
||||
"precip_mm": 0.03,
|
||||
"precip_in": 0.0,
|
||||
"humidity": 82,
|
||||
"cloud": 100,
|
||||
"feelslike_c": 6.9,
|
||||
"feelslike_f": 44.5,
|
||||
"windchill_c": 5.4,
|
||||
"windchill_f": 41.8,
|
||||
"heatindex_c": 9.0,
|
||||
"heatindex_f": 48.3,
|
||||
"dewpoint_c": 6.3,
|
||||
"dewpoint_f": 43.4,
|
||||
"vis_km": 10.0,
|
||||
"vis_miles": 6.0,
|
||||
"uv": 0.1,
|
||||
"gust_mph": 25.3,
|
||||
"gust_kph": 40.7,
|
||||
"air_quality": {
|
||||
"co": 155.678,
|
||||
"no2": 9.678,
|
||||
"o3": 45.0,
|
||||
"so2": 2.078,
|
||||
"pm2_5": 4.678,
|
||||
"pm10": 6.178,
|
||||
"us-epa-index": 1,
|
||||
"gb-defra-index": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
12
restapi/weather.http
Normal file
12
restapi/weather.http
Normal file
@@ -0,0 +1,12 @@
|
||||
@city = "grosshansdorf"
|
||||
@lang = en
|
||||
@forecast_days = 3
|
||||
# could be 60(mins) or 24(day)
|
||||
@time_period_forecast = 60
|
||||
@key = 3545ce42d0ba436e8dc164532250410
|
||||
|
||||
### aktuelles Wetter
|
||||
GET https://api.weatherapi.com/v1/current.json?key={{key}}&q={{city}}&aqi=yes&lang={{lang}}
|
||||
|
||||
### Vorhersage für n Tage (max 3 Tage for Free-Plan!)
|
||||
GET https://api.weatherapi.com/v1/forecast.json?q={{city}}&days={{forecast_days}}&tp={{time_period_forecast}}&key={{key}}&lang=de
|
||||
Reference in New Issue
Block a user