From 68f8a271061254c12ab73dff6b5a5f5f67dc7e10 Mon Sep 17 00:00:00 2001 From: evilbunny2008 <34211365+evilbunny2008@users.noreply.github.com> Date: Thu, 18 Nov 2021 17:40:28 +1100 Subject: [PATCH] Add met.no forecasts --- app/build.gradle | 10 +- .../com/odiousapps/weewxweather/Common.java | 302 +++++++++++++++++- .../com/odiousapps/weewxweather/Forecast.java | 10 + .../odiousapps/weewxweather/MainActivity.java | 4 + .../com/odiousapps/weewxweather/Weather.java | 20 ++ app/src/main/res/drawable/met_no.png | Bin 0 -> 14832 bytes build.gradle | 2 +- 7 files changed, 340 insertions(+), 8 deletions(-) create mode 100644 app/src/main/res/drawable/met_no.png diff --git a/app/build.gradle b/app/build.gradle index 387b6de..583a7d3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,8 +7,8 @@ android { minSdkVersion 19 //noinspection OldTargetApi targetSdkVersion 29 - versionCode 9010 - versionName "0.9.10" + versionCode 9011 + versionName "0.9.11" } buildTypes { release { @@ -21,10 +21,10 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(':colorpicker') - implementation 'androidx.appcompat:appcompat:1.2.0' - implementation 'androidx.constraintlayout:constraintlayout:2.0.4' + implementation 'androidx.appcompat:appcompat:1.3.1' + implementation 'androidx.constraintlayout:constraintlayout:2.1.1' implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" - implementation 'com.google.android.material:material:1.3.0' + implementation 'com.google.android.material:material:1.4.0' implementation 'rongi.rotate-layout:rotate-layout:3.0.0' implementation 'com.github.smart-fun:XmlToJson:1.4.4' implementation 'org.jsoup:jsoup:1.11.3' diff --git a/app/src/main/java/com/odiousapps/weewxweather/Common.java b/app/src/main/java/com/odiousapps/weewxweather/Common.java index 432467c..e6f9980 100644 --- a/app/src/main/java/com/odiousapps/weewxweather/Common.java +++ b/app/src/main/java/com/odiousapps/weewxweather/Common.java @@ -112,8 +112,7 @@ class Common PackageInfo version = pm.getPackageInfo("com.odiousapps.weewxweather", 0); appversion = version.versionName; LogMessage("appversion=" + appversion); - } catch (Exception e) - { + } catch (Exception e) { e.printStackTrace(); } } @@ -2279,6 +2278,305 @@ String[] processYR(String data, boolean showHeader) return new String[]{generateForecast(days, timestamp, showHeader), desc}; } + String[] processMetNO(String data) + { + return processMetNO(data, false); + } + + String[] processMetNO(String data, boolean showHeader) + { + if(data == null || data.equals("")) + return null; + + boolean metric = GetBoolPref("metric", true); + boolean use_icons = GetBoolPref("use_icons", false); + List days = new ArrayList<>(); + String desc = "MeVille"; + long timestamp; + + try + { +// desc = location.getString("name") + ", " + location.getString("country"); + + JSONObject jobj = new JSONObject(data); + jobj = jobj.getJSONObject("properties"); + String updated_at = jobj.getJSONObject("meta").getString("updated_at"); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX", Locale.getDefault()); + timestamp = sdf.parse(updated_at).getTime(); + JSONArray jarr = jobj.getJSONArray("timeseries"); + + if(jarr == null) + return null; + + for(int i = 0; i < jarr.length(); i++) + { + Day day = new Day(); + String time = jarr.getJSONObject(i).getString("time"); + day.timestamp = sdf.parse(time).getTime(); + + JSONObject tsdata = jarr.getJSONObject(i).getJSONObject("data"); + double temp = tsdata.getJSONObject("instant").getJSONObject("details").getDouble("air_temperature"); + if(metric) + day.max = round(temp) + "°C"; + else + day.max = round((temp * 9.0 / 5.0) + 32.0) + "°F"; + + String icon; + + try + { + try + { + double precip = tsdata.getJSONObject("next_1_hours").getJSONObject("details").getDouble("precipitation_amount"); + if(metric) + day.min = precip + "mm"; + else + day.min = (round(precip / 25.4 * 1000.0) / 1000.0) + "in"; + + icon = tsdata.getJSONObject("next_1_hours").getJSONObject("summary").getString("symbol_code"); + } catch (Exception e) { + double precip = tsdata.getJSONObject("next_6_hours").getJSONObject("details").getDouble("precipitation_amount"); + if(metric) + day.min = precip + "mm"; + else + day.min = (round(precip / 25.4 * 1000.0) / 1000.0) + "in"; + + icon = tsdata.getJSONObject("next_6_hours").getJSONObject("summary").getString("symbol_code"); + } + } catch (Exception e) { + continue; + } + + double windSpeed = tsdata.getJSONObject("instant").getJSONObject("details").getDouble("wind_speed"); + double windDir = tsdata.getJSONObject("instant").getJSONObject("details").getDouble("wind_from_direction"); + if(metric) + day.text = windSpeed + "m/s from the " + degtoname(windDir); + else + day.text = (round(windSpeed * 22.36936) / 10.0) + "mph from the " + degtoname(windDir); + + SimpleDateFormat sdf2 = new SimpleDateFormat("EEEE d, HH:mm", Locale.getDefault()); + day.day = sdf2.format(day.timestamp); + + LogMessage("time == " + time); + LogMessage("icon == " + icon); + String code = getCode(icon); + + if(!use_icons) + { + day.icon = "wi wi-yrno-" + code; + } else { + String fileName = checkImage("yrno" + code + ".png", null); + day.icon = "file://" + fileName; + } + + days.add(day); + } + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + return new String[]{generateForecast(days, timestamp, showHeader), desc}; + } + + private String degtoname(double deg) + { + if(deg <= 22.5) + return "North"; + else if(deg <= 67.5) + return "North East"; + else if(deg <= 112.5) + return "East"; + else if(deg <= 157.5) + return "South East"; + else if(deg <= 202.5) + return "South"; + else if(deg <= 247.5) + return "South West"; + else if(deg <= 292.5) + return "West"; + else if(deg <= 337.5) + return "North West"; + return "North"; + } + + private String getCode(String icon) + { + switch(icon) + { + case "clearsky_day": + return "01d"; + case "clearsky_night": + return "01n"; + case "clearsky_polartwilight": + return "01m"; + case "fair_day": + return "02d"; + case "fair_night": + return "02n"; + case "fair_polartwilight": + return "02m"; + case "partlycloudy_day": + return "03d"; + case "partlycloudy_night": + return "03n"; + case "partlycloudy_polartwilight": + return "03m"; + case "cloudy": + return "04"; + case "rainshowers_day": + return "05d"; + case "rainshowers_night": + return "05n"; + case "rainshowers_polartwilight": + return "05m"; + case "rainshowersandthunder_day": + return "06d"; + case "rainshowersandthunder_night": + return "06n"; + case "rainshowersandthunder_polartwilight": + return "06m"; + case "sleetshowers_day": + return "07d"; + case "sleetshowers_night": + return "07n"; + case "sleetshowers_polartwilight": + return "07m"; + case "snowshowers_day": + return "08d"; + case "snowshowers_night": + return "08n"; + case "snowshowers_polartwilight": + return "08m"; + case "rain": + return "09"; + case "heavyrain": + return "10"; + case "heavyrainandthunder": + return "11"; + case "sleet": + return "12"; + case "snow": + return "13"; + case "snowandthunder": + return "14"; + case "fog": + return "15"; + + case "sleetshowersandthunder_day": + return "20d"; + case "sleetshowersandthunder_night": + return "20n"; + case "sleetshowersandthunder_polartwilight": + return "20m"; + case "snowshowersandthunder_day": + return "21d"; + case "snowshowersandthunder_night": + return "21n"; + case "snowshowersandthunder_polartwilight": + return "21m"; + case "rainandthunder": + return "22"; + case "sleetandthunder": + return "23"; + case "lightrainshowersandthunder_day": + return "24d"; + case "lightrainshowersandthunder_night": + return "24n"; + case "lightrainshowersandthunder_polartwilight": + return "24m"; + case "heavyrainshowersandthunder_day": + return "25d"; + case "heavyrainshowersandthunder_night": + return "25n"; + case "heavyrainshowersandthunder_polartwilight": + return "25m"; + case "lightssleetshowersandthunder_day": + return "26d"; + case "lightssleetshowersandthunder_night": + return "26n"; + case "lightssleetshowersandthunder_polartwilight": + return "26m"; + case "heavysleetshowersandthunder_day": + return "27d"; + case "heavysleetshowersandthunder_night": + return "27n"; + case "heavysleetshowersandthunder_polartwilight": + return "27m"; + case "lightssnowshowersandthunder_day": + return "28d"; + case "lightssnowshowersandthunder_night": + return "28n"; + case "lightssnowshowersandthunder_polartwilight": + return "28m"; + case "heavysnowshowersandthunder_day": + return "29d"; + case "heavysnowshowersandthunder_night": + return "29n"; + case "heavysnowshowersandthunder_polartwilight": + return "29m"; + case "lightrainandthunder": + return "30"; + case "lightsleetandthunder": + return "31"; + case "heavysleetandthunder": + return "32"; + case "lightsnowandthunder": + return "33"; + case "heavysnowandthunder": + return "34"; + + case "lightrainshowers_day": + return "40d"; + case "lightrainshowers_night": + return "40n"; + case "lightrainshowers_polartwilight": + return "40m"; + case "heavyrainshowers_day": + return "41d"; + case "heavyrainshowers_night": + return "41n"; + case "heavyrainshowers_polartwilight": + return "41m"; + case "lightsleetshowers_day": + return "42d"; + case "lightsleetshowers_night": + return "42n"; + case "lightsleetshowers_polartwilight": + return "42m"; + case "heavysleetshowers_day": + return "43d"; + case "heavysleetshowers_night": + return "43n"; + case "heavysleetshowers_polartwilight": + return "43m"; + case "lightsnowshowers_day": + return "44d"; + case "lightsnowshowers_night": + return "44n"; + case "lightsnowshowers_polartwilight": + return "44m"; + case "heavysnowshowers_day": + return "45d"; + case "heavysnowshowers_night": + return "45n"; + case "heavysnowshowers_polartwilight": + return "45m"; + case "lightrain": + return "46"; + case "lightsleet": + return "47"; + case "heavysleet": + return "48"; + case "lightsnow": + return "49"; + case "heavysnow": + return "50"; + } + + return "01d"; + } + private long convertDaytoTS(String dayName, Locale locale, long lastTS) { long startTS = lastTS; diff --git a/app/src/main/java/com/odiousapps/weewxweather/Forecast.java b/app/src/main/java/com/odiousapps/weewxweather/Forecast.java index d9357e7..8ecee00 100644 --- a/app/src/main/java/com/odiousapps/weewxweather/Forecast.java +++ b/app/src/main/java/com/odiousapps/weewxweather/Forecast.java @@ -558,6 +558,13 @@ public void run() updateForecast(content[0], content[1]); break; } + case "met.no": + { + String[] content = common.processMetNO(data, true); + if(content != null && content.length >= 2) + updateForecast(content[0], content[1]); + break; + } case "bom.gov.au": { String[] content = common.processBOM(data, true); @@ -754,6 +761,9 @@ public void run() case "yr.no": im.setImageResource(R.drawable.yrno); break; + case "met.no": + im.setImageResource(R.drawable.met_no); + break; case "bom.gov.au": im.setImageResource(R.drawable.bom); if(dark_theme) diff --git a/app/src/main/java/com/odiousapps/weewxweather/MainActivity.java b/app/src/main/java/com/odiousapps/weewxweather/MainActivity.java index afaae96..172132a 100644 --- a/app/src/main/java/com/odiousapps/weewxweather/MainActivity.java +++ b/app/src/main/java/com/odiousapps/weewxweather/MainActivity.java @@ -614,6 +614,10 @@ public void run() Common.LogMessage("forecast=" + forecast); Common.LogMessage("fctype=" + fctype); break; + case "met.no": + Common.LogMessage("forecast=" + forecast); + Common.LogMessage("fctype=" + fctype); + break; case "bom.gov.au": bomtown = forecast.split(",")[1].trim(); common.SetStringPref("bomtown", bomtown); diff --git a/app/src/main/java/com/odiousapps/weewxweather/Weather.java b/app/src/main/java/com/odiousapps/weewxweather/Weather.java index f46cd48..f5412cc 100644 --- a/app/src/main/java/com/odiousapps/weewxweather/Weather.java +++ b/app/src/main/java/com/odiousapps/weewxweather/Weather.java @@ -483,6 +483,26 @@ public void run() sb.append(tmp); break; } + case "met.no": + { + String[] content = common.processMetNO(data); + if (content == null || content.length <= 0) + { + stopRefreshing(); + return; + } + + String logo = "
"; + sb.append(""); + if (dark_theme) + tmp = "" + Common.ssheader + ""; + else + tmp = "" + Common.ssheader + ""; + sb.append(tmp); + tmp = "" + logo + content[0] + ""; + sb.append(tmp); + break; + } case "bom.gov.au": { String[] content = common.processBOM(data); diff --git a/app/src/main/res/drawable/met_no.png b/app/src/main/res/drawable/met_no.png new file mode 100644 index 0000000000000000000000000000000000000000..42cfa9e4add98922a22ae734799be70c0f13fb87 GIT binary patch literal 14832 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