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.WeatherProvider
|
||||
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.metno.MetNoProvider
|
||||
import de.mm20.launcher2.weather.openweathermap.OpenWeatherMapProvider
|
||||
@ -58,6 +59,9 @@ class PreferencesWeatherFragment : PreferenceFragmentCompat() {
|
||||
MetNoProvider(context).takeIf { it.isAvailable() }?.let {
|
||||
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()) {
|
||||
providerPref.summary = context.getString(
|
||||
|
||||
@ -154,6 +154,7 @@
|
||||
<string name="websearch_dialog_url_error">In dieser URL fehlt der Platzhalter „${1}“</string>
|
||||
<string name="preference_weather_provider">Wetterdienst</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="date_format_long_without_year">EE, d. MMMM</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_lightrainandthunder">Leichter Regen und Gewitter</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_heavyrainshowers">Starke Regenschauer</string>
|
||||
<string name="weather_rainshowersandthunder">Regenschauer und Gewitter</string>
|
||||
|
||||
@ -193,6 +193,7 @@
|
||||
<string name="preference_weather_provider">Provider</string>
|
||||
<string name="provider_metno">MET Norway</string>
|
||||
<string name="provider_openweathermap">OpenWeatherMap</string>
|
||||
<string name="provider_brightsky">Deutscher Wetterdienst (Germany only)</string>
|
||||
<string name="provider_here">HERE</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>
|
||||
@ -406,6 +407,8 @@
|
||||
<string name="weather_cloudy">Cloudy</string>
|
||||
<string name="weather_lightrainandthunder">Light rain and thunder</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_heavyrainshowers">Heavy rain showers</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 {
|
||||
OPENWEATHERMAP("0"),
|
||||
HERE("3"),
|
||||
MET_NO("2");
|
||||
MET_NO("2"),
|
||||
BRIGHT_SKY("4");
|
||||
|
||||
companion object {
|
||||
fun byValue(value: String): WeatherProviders {
|
||||
|
||||
@ -9,6 +9,7 @@ import androidx.core.content.getSystemService
|
||||
import de.mm20.launcher2.ktx.checkPermission
|
||||
import de.mm20.launcher2.preferences.LauncherPreferences
|
||||
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.metno.MetNoProvider
|
||||
import de.mm20.launcher2.weather.openweathermap.OpenWeatherMapProvider
|
||||
@ -103,6 +104,7 @@ abstract class WeatherProvider<T : WeatherLocation> {
|
||||
return when (LauncherPreferences.instance.weatherProvider) {
|
||||
WeatherProviders.OPENWEATHERMAP -> OpenWeatherMapProvider(context)
|
||||
WeatherProviders.HERE -> HereProvider(context)
|
||||
WeatherProviders.BRIGHT_SKY -> BrightskyProvider(context)
|
||||
else -> MetNoProvider(context)
|
||||
}.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