summaryrefslogtreecommitdiff
path: root/services/Weather.qml
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--services/Weather.qml142
1 files changed, 131 insertions, 11 deletions
diff --git a/services/Weather.qml b/services/Weather.qml
index 73e0b77..bc1f11c 100644
--- a/services/Weather.qml
+++ b/services/Weather.qml
@@ -10,29 +10,149 @@ Singleton {
id: root
property string city
+ property string loc
property var cc
property var forecast
+
readonly property string icon: cc ? Icons.getWeatherIcon(cc.weatherCode) : "cloud_alert"
- readonly property string description: cc?.weatherDesc[0].value ?? qsTr("No weather")
+ readonly property string description: cc?.weatherDesc ?? qsTr("No weather")
readonly property string temp: Config.services.useFahrenheit ? `${cc?.temp_F ?? 0}°F` : `${cc?.temp_C ?? 0}°C`
readonly property string feelsLike: Config.services.useFahrenheit ? `${cc?.FeelsLikeF ?? 0}°F` : `${cc?.FeelsLikeC ?? 0}°C`
readonly property int humidity: cc?.humidity ?? 0
+ readonly property real windSpeed: (cc && cc.windSpeed !== undefined) ? cc.windSpeed : 0.0
+ readonly property string sunrise: cc ? Qt.formatDateTime(new Date(cc.sunrise), Config.services.useTwelveHourClock ? "h:mm A" : "h:mm") : "--:--"
+ readonly property string sunset: cc ? Qt.formatDateTime(new Date(cc.sunset), Config.services.useTwelveHourClock ? "h:mm A" : "h:mm") : "--:--"
function reload(): void {
- if (Config.services.weatherLocation)
- city = Config.services.weatherLocation;
- else if (!city || timer.elapsed() > 900)
+ let configLocation = Config.services.weatherLocation;
+
+ if (configLocation && configLocation !== "") {
+ if (configLocation.indexOf(",") !== -1 && !isNaN(parseFloat(configLocation.split(",")[0])))
+ loc = configLocation;
+ else
+ fetchCoordsFromCity(configLocation);
+ } else if (!loc || timer.elapsed() > 900) {
Requests.get("https://ipinfo.io/json", text => {
- city = JSON.parse(text).city ?? "";
- timer.restart();
+ const response = JSON.parse(text);
+ if (response.loc) {
+ loc = response.loc;
+ city = response.city ?? "";
+ timer.restart();
+ }
});
+ }
+ }
+
+ function fetchCoordsFromCity(cityName) {
+ const url = "https://geocoding-api.open-meteo.com/v1/search?name=" + encodeURIComponent(cityName) + "&count=1&language=en&format=json";
+
+ Requests.get(url, text => {
+ const json = JSON.parse(text);
+ if (json.results && json.results.length > 0) {
+ const result = json.results[0];
+ loc = result.latitude + "," + result.longitude;
+ city = result.name;
+ } else {
+ loc = "";
+ reload();
+ }
+ });
}
- onCityChanged: Requests.get(`https://wttr.in/${city}?format=j1`, text => {
- const json = JSON.parse(text);
- cc = json.current_condition[0];
- forecast = json.weather;
- })
+ function fetchWeatherData() {
+ const url = getWeatherUrl();
+ if (url === "")
+ return;
+
+ Requests.get(url, text => {
+ const json = JSON.parse(text);
+ if (!json.current || !json.daily)
+ return;
+
+ cc = {
+ "weatherCode": String(json.current.weather_code),
+ "weatherDesc": getWeatherCondition(String(json.current.weather_code)),
+ "temp_C": Math.round(json.current.temperature_2m),
+ "temp_F": Math.round(json.current.temperature_2m * 9 / 5 + 32),
+ "FeelsLikeC": Math.round(json.current.apparent_temperature),
+ "FeelsLikeF": Math.round(json.current.apparent_temperature * 9 / 5 + 32),
+ "humidity": json.current.relative_humidity_2m,
+ "windSpeed": json.current.wind_speed_10m,
+ "isDay": json.current.is_day,
+ "sunrise": json.daily.sunrise[0],
+ "sunset": json.daily.sunset[0]
+ };
+
+ const forecastList = [];
+ for (let i = 0; i < json.daily.time.length; i++)
+ forecastList.push({
+ "date": json.daily.time[i],
+ "maxTempC": Math.round(json.daily.temperature_2m_max[i]),
+ "maxTempF": Math.round(json.daily.temperature_2m_max[i] * 9 / 5 + 32),
+ "minTempC": Math.round(json.daily.temperature_2m_min[i]),
+ "minTempF": Math.round(json.daily.temperature_2m_min[i] * 9 / 5 + 32),
+ "weatherCode": String(json.daily.weather_code[i]),
+ "icon": Icons.getWeatherIcon(String(json.daily.weather_code[i]))
+ });
+
+ forecast = forecastList;
+ });
+ }
+
+ function getWeatherUrl() {
+ if (!loc || loc.indexOf(",") === -1)
+ return "";
+
+ const [lat, lon] = loc.split(",");
+ const baseUrl = "https://api.open-meteo.com/v1/forecast";
+ const params = ["latitude=" + lat, "longitude=" + lon, "daily=weather_code,temperature_2m_max,temperature_2m_min,sunrise,sunset", "current=temperature_2m,relative_humidity_2m,apparent_temperature,is_day,weather_code,wind_speed_10m", "timezone=auto", "forecast_days=7"];
+
+ return baseUrl + "?" + params.join("&");
+ }
+
+ function getWeatherCondition(code: string): string {
+ const conditions = {
+ "0": "Clear",
+ "1": "Clear",
+ "2": "Partly cloudy",
+ "3": "Overcast",
+ "45": "Fog",
+ "48": "Fog",
+ "51": "Drizzle",
+ "53": "Drizzle",
+ "55": "Drizzle",
+ "56": "Freezing drizzle",
+ "57": "Freezing drizzle",
+ "61": "Light rain",
+ "63": "Rain",
+ "65": "Heavy rain",
+ "66": "Light rain",
+ "67": "Heavy rain",
+ "71": "Light snow",
+ "73": "Snow",
+ "75": "Heavy snow",
+ "77": "Snow",
+ "80": "Light rain",
+ "81": "Rain",
+ "82": "Heavy rain",
+ "85": "Light snow showers",
+ "86": "Heavy snow showers",
+ "95": "Thunderstorm",
+ "96": "Thunderstorm with hail",
+ "99": "Thunderstorm with hail"
+ };
+ return conditions[code] || "Unknown";
+ }
+
+ onLocChanged: fetchWeatherData()
+
+ // Refresh current location hourly
+ Timer {
+ interval: 3600000 // 1 hour
+ running: true
+ repeat: true
+ onTriggered: fetchWeatherData()
+ }
ElapsedTimer {
id: timer