Add Bright Sky (Deutscher Wetterdienst) weather provider
This commit is contained in:
parent
b8b936f182
commit
cb44e24ae1
@ -16,6 +16,7 @@ import de.mm20.launcher2.preferences.WeatherProviders
|
|||||||
import de.mm20.launcher2.weather.WeatherLocation
|
import de.mm20.launcher2.weather.WeatherLocation
|
||||||
import de.mm20.launcher2.weather.WeatherProvider
|
import de.mm20.launcher2.weather.WeatherProvider
|
||||||
import de.mm20.launcher2.weather.WeatherViewModel
|
import de.mm20.launcher2.weather.WeatherViewModel
|
||||||
|
import de.mm20.launcher2.weather.brightsky.BrightskyProvider
|
||||||
import de.mm20.launcher2.weather.here.HereProvider
|
import de.mm20.launcher2.weather.here.HereProvider
|
||||||
import de.mm20.launcher2.weather.metno.MetNoProvider
|
import de.mm20.launcher2.weather.metno.MetNoProvider
|
||||||
import de.mm20.launcher2.weather.openweathermap.OpenWeatherMapProvider
|
import de.mm20.launcher2.weather.openweathermap.OpenWeatherMapProvider
|
||||||
@ -58,6 +59,9 @@ class PreferencesWeatherFragment : PreferenceFragmentCompat() {
|
|||||||
MetNoProvider(context).takeIf { it.isAvailable() }?.let {
|
MetNoProvider(context).takeIf { it.isAvailable() }?.let {
|
||||||
providers.add(WeatherProviders.MET_NO to it.name)
|
providers.add(WeatherProviders.MET_NO to it.name)
|
||||||
}
|
}
|
||||||
|
BrightskyProvider(context).takeIf { it.isAvailable() }?.let {
|
||||||
|
providers.add(WeatherProviders.BRIGHT_SKY to it.name)
|
||||||
|
}
|
||||||
|
|
||||||
if (providers.isEmpty()) {
|
if (providers.isEmpty()) {
|
||||||
providerPref.summary = context.getString(
|
providerPref.summary = context.getString(
|
||||||
|
|||||||
@ -154,6 +154,7 @@
|
|||||||
<string name="websearch_dialog_url_error">In dieser URL fehlt der Platzhalter „${1}“</string>
|
<string name="websearch_dialog_url_error">In dieser URL fehlt der Platzhalter „${1}“</string>
|
||||||
<string name="preference_weather_provider">Wetterdienst</string>
|
<string name="preference_weather_provider">Wetterdienst</string>
|
||||||
<string name="provider_openweathermap">OpenWeatherMap</string>
|
<string name="provider_openweathermap">OpenWeatherMap</string>
|
||||||
|
<string name="provider_brightsky">Deutscher Wetterdienst (nur Deutschland)</string>
|
||||||
<string name="preference_automatic_location_disabled_summary">Von diesem Wetterdienst nicht unterstützt</string>
|
<string name="preference_automatic_location_disabled_summary">Von diesem Wetterdienst nicht unterstützt</string>
|
||||||
<string name="date_format_long_without_year">EE, d. MMMM</string>
|
<string name="date_format_long_without_year">EE, d. MMMM</string>
|
||||||
<string name="weather_wind_direction_speed">%1$s • %2$s</string>
|
<string name="weather_wind_direction_speed">%1$s • %2$s</string>
|
||||||
@ -253,6 +254,8 @@
|
|||||||
<string name="weather_cloudy">Bedeckt</string>
|
<string name="weather_cloudy">Bedeckt</string>
|
||||||
<string name="weather_lightrainandthunder">Leichter Regen und Gewitter</string>
|
<string name="weather_lightrainandthunder">Leichter Regen und Gewitter</string>
|
||||||
<string name="weather_snow">Schneefall</string>
|
<string name="weather_snow">Schneefall</string>
|
||||||
|
<string name="weather_hail">Hagel</string>
|
||||||
|
<string name="weather_thunder">Gewitter</string>
|
||||||
<string name="weather_heavysnowshowers">Starke Schneeschauer</string>
|
<string name="weather_heavysnowshowers">Starke Schneeschauer</string>
|
||||||
<string name="weather_heavyrainshowers">Starke Regenschauer</string>
|
<string name="weather_heavyrainshowers">Starke Regenschauer</string>
|
||||||
<string name="weather_rainshowersandthunder">Regenschauer und Gewitter</string>
|
<string name="weather_rainshowersandthunder">Regenschauer und Gewitter</string>
|
||||||
|
|||||||
@ -193,6 +193,7 @@
|
|||||||
<string name="preference_weather_provider">Provider</string>
|
<string name="preference_weather_provider">Provider</string>
|
||||||
<string name="provider_metno">MET Norway</string>
|
<string name="provider_metno">MET Norway</string>
|
||||||
<string name="provider_openweathermap">OpenWeatherMap</string>
|
<string name="provider_openweathermap">OpenWeatherMap</string>
|
||||||
|
<string name="provider_brightsky">Deutscher Wetterdienst (Germany only)</string>
|
||||||
<string name="provider_here">HERE</string>
|
<string name="provider_here">HERE</string>
|
||||||
<string name="preference_automatic_location_disabled_summary">Not supported by this provider</string>
|
<string name="preference_automatic_location_disabled_summary">Not supported by this provider</string>
|
||||||
<string name="date_format_long_without_year">EE, MMMM d</string>
|
<string name="date_format_long_without_year">EE, MMMM d</string>
|
||||||
@ -406,6 +407,8 @@
|
|||||||
<string name="weather_cloudy">Cloudy</string>
|
<string name="weather_cloudy">Cloudy</string>
|
||||||
<string name="weather_lightrainandthunder">Light rain and thunder</string>
|
<string name="weather_lightrainandthunder">Light rain and thunder</string>
|
||||||
<string name="weather_snow">Snow</string>
|
<string name="weather_snow">Snow</string>
|
||||||
|
<string name="weather_hail">Hail</string>
|
||||||
|
<string name="weather_thunder">Thunderstorm</string>
|
||||||
<string name="weather_heavysnowshowers">Heavy snow showers</string>
|
<string name="weather_heavysnowshowers">Heavy snow showers</string>
|
||||||
<string name="weather_heavyrainshowers">Heavy rain showers</string>
|
<string name="weather_heavyrainshowers">Heavy rain showers</string>
|
||||||
<string name="weather_rainshowersandthunder">Rain showers and thunder</string>
|
<string name="weather_rainshowersandthunder">Rain showers and thunder</string>
|
||||||
|
|||||||
@ -159,7 +159,8 @@ enum class IconShape(override val value: String) : PreferenceEnum {
|
|||||||
enum class WeatherProviders(override val value: String) : PreferenceEnum {
|
enum class WeatherProviders(override val value: String) : PreferenceEnum {
|
||||||
OPENWEATHERMAP("0"),
|
OPENWEATHERMAP("0"),
|
||||||
HERE("3"),
|
HERE("3"),
|
||||||
MET_NO("2");
|
MET_NO("2"),
|
||||||
|
BRIGHT_SKY("4");
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun byValue(value: String): WeatherProviders {
|
fun byValue(value: String): WeatherProviders {
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import androidx.core.content.getSystemService
|
|||||||
import de.mm20.launcher2.ktx.checkPermission
|
import de.mm20.launcher2.ktx.checkPermission
|
||||||
import de.mm20.launcher2.preferences.LauncherPreferences
|
import de.mm20.launcher2.preferences.LauncherPreferences
|
||||||
import de.mm20.launcher2.preferences.WeatherProviders
|
import de.mm20.launcher2.preferences.WeatherProviders
|
||||||
|
import de.mm20.launcher2.weather.brightsky.BrightskyProvider
|
||||||
import de.mm20.launcher2.weather.here.HereProvider
|
import de.mm20.launcher2.weather.here.HereProvider
|
||||||
import de.mm20.launcher2.weather.metno.MetNoProvider
|
import de.mm20.launcher2.weather.metno.MetNoProvider
|
||||||
import de.mm20.launcher2.weather.openweathermap.OpenWeatherMapProvider
|
import de.mm20.launcher2.weather.openweathermap.OpenWeatherMapProvider
|
||||||
@ -103,6 +104,7 @@ abstract class WeatherProvider<T : WeatherLocation> {
|
|||||||
return when (LauncherPreferences.instance.weatherProvider) {
|
return when (LauncherPreferences.instance.weatherProvider) {
|
||||||
WeatherProviders.OPENWEATHERMAP -> OpenWeatherMapProvider(context)
|
WeatherProviders.OPENWEATHERMAP -> OpenWeatherMapProvider(context)
|
||||||
WeatherProviders.HERE -> HereProvider(context)
|
WeatherProviders.HERE -> HereProvider(context)
|
||||||
|
WeatherProviders.BRIGHT_SKY -> BrightskyProvider(context)
|
||||||
else -> MetNoProvider(context)
|
else -> MetNoProvider(context)
|
||||||
}.takeIf { it.isAvailable() }
|
}.takeIf { it.isAvailable() }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,38 @@
|
|||||||
|
package de.mm20.launcher2.weather.brightsky
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.Query
|
||||||
|
|
||||||
|
data class BrightSkyResult(
|
||||||
|
val weather: Array<BrightSkyResultWether>
|
||||||
|
)
|
||||||
|
|
||||||
|
data class BrightSkyResultWether(
|
||||||
|
val timestamp: String?,
|
||||||
|
@SerializedName("source_id") val sourceId: Int?,
|
||||||
|
@SerializedName("cloud_cover") val cloudCover: Double?,
|
||||||
|
val condition: String?,
|
||||||
|
@SerializedName("dew_point") val dewPoint: Double?,
|
||||||
|
val icon: String?,
|
||||||
|
val precipitation: Double?,
|
||||||
|
@SerializedName("pressure_msl") val pressureMsl: Double?,
|
||||||
|
@SerializedName("relative_humidity") val relativeHumidity: Double?,
|
||||||
|
val sunshine: Double?,
|
||||||
|
val temperature: Double?,
|
||||||
|
val visibility: Double?,
|
||||||
|
@SerializedName("wind_direction") val windDirection: Double?,
|
||||||
|
@SerializedName("wind_speed") val windSpeed: Double?,
|
||||||
|
@SerializedName("wind_gust_direction") val windGustDirection: Double?,
|
||||||
|
@SerializedName("wind_gust_speed") val windGustSpeed: Double?,
|
||||||
|
)
|
||||||
|
|
||||||
|
interface BrightSkyApi {
|
||||||
|
@GET("/weather?units=si")
|
||||||
|
suspend fun weather(
|
||||||
|
@Query("date") date: String,
|
||||||
|
@Query("last_date") lastDate: String,
|
||||||
|
@Query("lat") lat: Double,
|
||||||
|
@Query("lon") lon: Double,
|
||||||
|
): BrightSkyResult
|
||||||
|
}
|
||||||
@ -0,0 +1,129 @@
|
|||||||
|
package de.mm20.launcher2.weather.brightsky
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import android.icu.text.SimpleDateFormat
|
||||||
|
import android.icu.util.Calendar
|
||||||
|
import de.mm20.launcher2.crashreporter.CrashReporter
|
||||||
|
import de.mm20.launcher2.weather.*
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
import retrofit2.create
|
||||||
|
import java.lang.Exception
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
class BrightskyProvider(
|
||||||
|
override val context: Context
|
||||||
|
) : LatLonWeatherProvider() {
|
||||||
|
|
||||||
|
|
||||||
|
val apiClient by lazy {
|
||||||
|
val retrofit = Retrofit.Builder()
|
||||||
|
.baseUrl("https://api.brightsky.dev/")
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.build()
|
||||||
|
retrofit.create<BrightSkyApi>()
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun loadWeatherData(location: LatLonWeatherLocation): WeatherUpdateResult<LatLonWeatherLocation>? {
|
||||||
|
|
||||||
|
val result = runCatching {
|
||||||
|
val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
|
||||||
|
val date = Calendar.getInstance()
|
||||||
|
date.timeInMillis -= 1000 * 60 * 30
|
||||||
|
val startDate = format.format(date.timeInMillis)
|
||||||
|
date.timeInMillis += 1000 * 60 * 60 * 24 * 14
|
||||||
|
val endDate = format.format(date.timeInMillis)
|
||||||
|
apiClient.weather(
|
||||||
|
date = startDate,
|
||||||
|
lastDate = endDate,
|
||||||
|
lat = location.lat,
|
||||||
|
lon = location.lon,
|
||||||
|
)
|
||||||
|
}.getOrElse {
|
||||||
|
CrashReporter.logException(Exception(it))
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")
|
||||||
|
val forecasts = mutableListOf<Forecast>()
|
||||||
|
val updateTime = System.currentTimeMillis()
|
||||||
|
for (weather in result.weather) {
|
||||||
|
forecasts.add(
|
||||||
|
Forecast(
|
||||||
|
timestamp = format.parse(weather.timestamp)?.time ?: continue,
|
||||||
|
clouds = weather.cloudCover?.roundToInt() ?: -1,
|
||||||
|
condition = getCondition(weather.icon ?: continue) ?: continue,
|
||||||
|
humidity = weather.relativeHumidity ?: -1.0,
|
||||||
|
icon = getIcon(weather.icon) ?: continue,
|
||||||
|
location = location.name,
|
||||||
|
maxTemp = weather.temperature ?: continue,
|
||||||
|
minTemp = weather.temperature,
|
||||||
|
night = (weather.sunshine ?: 100.0).roundToInt() == 0,
|
||||||
|
pressure = weather.pressureMsl ?: -1.0,
|
||||||
|
provider = "Deutscher Wetterdienst",
|
||||||
|
providerUrl = "https://www.dwd.de/",
|
||||||
|
precipitation = weather.precipitation ?: -1.0,
|
||||||
|
precipProbability = -1,
|
||||||
|
temperature = weather.temperature,
|
||||||
|
updateTime = updateTime,
|
||||||
|
windDirection = weather.windDirection ?: -1.0,
|
||||||
|
windSpeed = weather.windSpeed ?: -1.0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return WeatherUpdateResult(
|
||||||
|
forecasts, location
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getIcon(icon: String): Int? {
|
||||||
|
return when (icon) {
|
||||||
|
"clear-day", "clear-night" -> Forecast.CLEAR
|
||||||
|
"partly-cloudy-day", "partly-cloudy-night" -> Forecast.PARTLY_CLOUDY
|
||||||
|
"cloudy" -> Forecast.CLOUDY
|
||||||
|
"fog" -> Forecast.FOG
|
||||||
|
"wind" -> Forecast.WIND
|
||||||
|
"rain" -> Forecast.SHOWERS
|
||||||
|
"sleet" -> Forecast.SLEET
|
||||||
|
"snow" -> Forecast.SNOW
|
||||||
|
"hail" -> Forecast.HAIL
|
||||||
|
"thunderstorm" -> Forecast.THUNDERSTORM
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getCondition(icon: String): String? {
|
||||||
|
val resId = when (icon) {
|
||||||
|
"clear-day", "clear-night" -> R.string.weather_clearsky
|
||||||
|
"partly-cloudy-day", "partly-cloudy-night" -> R.string.weather_partlycloudy
|
||||||
|
"cloudy" -> R.string.weather_cloudy
|
||||||
|
"fog" -> R.string.weather_fog
|
||||||
|
"wind" -> R.string.weather_wind
|
||||||
|
"rain" -> R.string.weather_rain
|
||||||
|
"sleet" -> R.string.weather_sleet
|
||||||
|
"snow" -> R.string.weather_snow
|
||||||
|
"hail" -> R.string.weather_hail
|
||||||
|
"thunderstorm" -> R.string.weather_thunder
|
||||||
|
else -> return null
|
||||||
|
}
|
||||||
|
return context.getString(resId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val preferences: SharedPreferences
|
||||||
|
get() = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
|
||||||
|
|
||||||
|
override fun isUpdateRequired(): Boolean {
|
||||||
|
return getLastUpdate() + 3600000 < System.currentTimeMillis()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isAvailable(): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override val name: String
|
||||||
|
get() = context.getString(R.string.provider_brightsky)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PREFS = "bright_sky"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user